home *** CD-ROM | disk | FTP | other *** search
/ Creative Computers / Creative Computers CD-ROM, Volume 1 (Legendary Design Technologies, Inc.)(1994).iso / shareware / fractals / mandelsquare / mandelsquare-1.06.lha / MandelSquare.c < prev    next >
C/C++ Source or Header  |  1992-12-20  |  100KB  |  4,326 lines

  1. /*
  2. **    MandelSquare - AmigaDOS 2.0/3.0 Mandelbrot set explorer
  3. **
  4. **    MandelSquare.c, Main program module
  5. **
  6. **    Copyright © 1991-1992 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "MandelSquare.h"
  11.  
  12. UBYTE VersTag[]    = VERSTAG;
  13.  
  14.     /* Menu IDs */
  15.  
  16. enum    {    MEN_OPEN=17,MEN_SAVE,MEN_SAVEAS,MEN_PRI0,MEN_PRI1,MEN_PRI2,MEN_PLAY,MEN_START,MEN_STOP,MEN_SCROLL,MEN_FRAME,MEN_INCLUDE,MEN_RESOLUTION,MEN_ABOUT,MEN_QUIT,
  17.         MEN_ZOOM,MEN_CLIP,MEN_RERUN,MEN_PRECISE,MEN_COORDS,MEN_PALETTE,MEN_RUN };
  18.  
  19.     /* Dimensions of the coords control panel. */
  20.  
  21. #define COORDS_WIDTH        256
  22. #define COORDS_HEIGHT        120
  23.  
  24.     /* Dimensions of the palette control panel. */
  25.  
  26. #define PALETTE_WIDTH        245
  27. #define PALETTE_HEIGHT        53
  28.  
  29.     /* Dimensions of the scroll amount control panel. */
  30.  
  31. #define SCROLL_WIDTH        175
  32. #define SCROLL_HEIGHT        45
  33.  
  34.     /* A handy macro to set the window mouse pointer. */
  35.  
  36. #define SetClear(Window)    SetPointer(Window,ClearData, 1,16, 0,0)
  37.  
  38.     /* Some handy signal names. */
  39.  
  40. #define SIG_KILL        SIGBREAKF_CTRL_C
  41. #define SIG_HANDSHAKE        SIGBREAKF_CTRL_F
  42. #define SIG_TIMER        (1 << TimePort -> mp_SigBit)
  43. #define SIG_WINDOW        (1 << Window -> UserPort -> mp_SigBit)
  44.  
  45.     /* A second measured in microseconds. */
  46.  
  47. #define SECOND            1000000
  48.  
  49.     /* A picture info structure as returned by LoadPicture(). */
  50.  
  51. struct PictureInfo
  52. {
  53.     BitMapHeader        BitMapHeader;
  54.     MandelHeader        MandelHeader;
  55.     struct Palette *    Palette;
  56.     ULONG            ViewModes;
  57.     struct BitMap *        BitMap;
  58. };
  59.  
  60.     /* In Plot.asm and Iterate.asm */
  61.  
  62. extern VOID __asm        Plot(register __a0 struct BitMap *,register __d0 WORD X,register __d1 WORD Y,register __d2 WORD Colour);
  63. extern BYTE __asm        Test(register __a0 struct BitMap *,register __d0 WORD X,register __d1 WORD Y);
  64. extern UBYTE __asm        Iterate(register __fp0 double const RealValue,register __fp1 double const ImaginaryValue);
  65.  
  66.     /* In Mandelbrot.c */
  67.  
  68. VOID                SetWait(struct Window *Window);
  69. VOID                ClrWait(struct Window *Window);
  70. VOID __regargs            CycleColours(BYTE Forward);
  71. LONG __regargs            GetModeSize(ULONG ID);
  72. BYTE __regargs            SelectDisplayMode(struct Window *Window,ULONG *Mode);
  73. VOID __regargs            DrawSquare(struct RastPort *RPort,WORD X,WORD Y,WORD Width);
  74. VOID __regargs            DrawLine(struct RastPort *RPort,UWORD FromX,UWORD FromY,UWORD ToX,UWORD ToY);
  75. VOID                IterationSetup(VOID);
  76. VOID __saveds            CycleServer(VOID);
  77. VOID                CloseWindowSafely(struct Window *Window);
  78. VOID                GfxCleanup(VOID);
  79. LONG                GfxSetup(VOID);
  80. VOID __regargs            CloseAll(LONG ReturnCode);
  81. VOID                OpenAll(VOID);
  82. VOID __regargs            CopyLine(struct BitMap *BitMap,WORD Line);
  83. VOID                GetTime(VOID);
  84. VOID                BlockWindow(VOID);
  85. VOID                ReleaseWindow(VOID);
  86. BYTE                GetFile(UBYTE *Title,UBYTE *Directory,UBYTE *Name,UBYTE *Buffer,UBYTE *Pattern,BYTE SaveFlag);
  87. WORD __stdargs            MyEasyRequest(UBYTE *Gadgets,UBYTE *Text,...);
  88. ULONG __regargs            Random(LONG MaxValue);
  89. struct Gadget *            CreateAllCoordsGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge);
  90. struct Gadget *            CreateAllPaletteGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge);
  91. struct Gadget *            CreateAllScrollGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge);
  92. VOID                InfoText(VOID);
  93. WORD                CalculateFrames(double MinReal,double MinImaginary,double Size);
  94. VOID                RunAnim(VOID);
  95. VOID                StopAnim(VOID);
  96. VOID                Coords(VOID);
  97. VOID                AdjustPalette(VOID);
  98. VOID                MaxScrollPanel(VOID);
  99. VOID                AreaZoom(VOID);
  100. VOID                Zoom(VOID);
  101. VOID                HandleEvent(VOID);
  102. VOID                Mandelbrot(double MinReal,double MinImaginary,double RealStep,double ImaginaryStep,LONG Left,LONG Top,LONG Width,LONG Height);
  103. VOID                RunMandelbrot(double MinReal,double MaxReal,double MinImaginary,double MaxImaginary,LONG Width,LONG Height);
  104. VOID                RunAreaMandelbrot(double RealStep,double ImaginaryStep);
  105. BYTE                CheckAbort(VOID);
  106. BYTE                ReplayAnim(VOID);
  107. VOID __stdargs            main(VOID);
  108.  
  109.     /* In PlayAnim.c */
  110.  
  111. VOID                DeleteAnim(struct MinList *List);
  112. struct MinList *        LoadAnim(STRPTR Name);
  113. LONG                ValidateAnim(struct MinList *List,struct Screen *Screen);
  114. BYTE                PlayAnim(struct MinList *List,struct Screen *Screen,BYTE (*CheckAbort)(VOID));
  115.  
  116.     /* In SaveAnim.c */
  117.  
  118. struct AnimInfo *        OpenAnim(STRPTR Name,struct Screen *Screen);
  119. BYTE                AddAnim(struct AnimInfo *Info);
  120. VOID                CloseAnim(struct AnimInfo *Info,BYTE Success);
  121.  
  122.     /* In ILBM.c */
  123.  
  124. VOID                FreeCustomBitMap(struct BitMap *BitMap,BYTE Standard);
  125. struct BitMap *            AllocCustomBitMap(UWORD Depth,UWORD Width,UWORD Height,BYTE Standard);
  126.  
  127. VOID                FreePicture(struct PictureInfo *Info);
  128. struct PictureInfo *        LoadPicture(STRPTR Name);
  129. BYTE                SavePicture(STRPTR Name,struct Screen *Screen,MandelHeader *MandelHeader);
  130.  
  131.     /* In Palette.c */
  132.  
  133. VOID                FreePalette(struct Palette *Palette);
  134. struct Palette *        AllocPalette(LONG NumColours,BYTE TrueColour);
  135. struct Palette *        GetPalette(struct Screen *Screen,struct Palette *Palette);
  136. VOID                LoadPalette(struct Screen *Screen,struct Palette *Palette,LONG NumColours);
  137. LONG                GetPaletteSize(struct Palette *Palette);
  138. BYTE                GetPaletteTriplet(struct Palette *Palette,UBYTE *Triplet,LONG Index);
  139. BYTE                SetPaletteTriplet(struct Palette *Palette,UBYTE R,UBYTE G,UBYTE B,LONG Index);
  140. ULONG                GetPaletteEntry(struct Palette *Palette,LONG Index);
  141. BYTE                SetPaletteEntry(struct Palette *Palette,ULONG Entry,LONG Index);
  142.  
  143.     /* Shared and global library data. */
  144.  
  145. struct IntuitionBase        *IntuitionBase;
  146. struct GfxBase            *GfxBase;
  147. struct Library            *GadToolsBase;
  148. struct Library            *IFFParseBase;
  149. struct Library            *AslBase;
  150. struct Library            *TimerBase;
  151. struct Library            *IconBase;
  152.  
  153.     /* Timer data. */
  154.  
  155. struct timerequest        *TimeRequest;
  156. struct MsgPort            *TimePort;
  157.  
  158.     /* Window & Screen data. */
  159.  
  160. struct Screen            *Screen;
  161. struct Window            *Window;
  162. struct RastPort            *RPort;
  163. struct ViewPort            *VPort;
  164. APTR                 VisualInfo;
  165. struct BitMap            *BackupBitMap;
  166. struct Menu            *Menu;
  167.  
  168.     /* Current process and Window Pointer. */
  169.  
  170. struct Process            *ThisProcess;
  171. APTR                 OldPtr;
  172. BYTE                 OldPri;
  173.  
  174.     /* Colour cycling data. */
  175.  
  176. struct Task            *CycleTask;
  177. BYTE                 DoCycle    = FALSE,
  178.                  Add        = 0,
  179.                  Forward;
  180.  
  181.     /* Some strings. */
  182.  
  183. UBYTE                 LastName[256],
  184.                  NameBuffer[256],
  185.                  DummyBuffer[256],
  186.                  AnimSaveName[256],
  187.                  AnimPlayName[256];
  188.  
  189.     /* Calculation data. */
  190.  
  191. LONG                 MaxIteration        = 32 - 1;
  192.  
  193. double                 MaxScroll        = 4,
  194.  
  195.                  RealStep,
  196.                  ImaginaryStep,
  197.  
  198.                  RealWidth        = 4.5,
  199.                  ImaginaryHeight    = 4.5,
  200.  
  201.                  MinReal,
  202.                  MinImaginary,
  203.  
  204.                  MainMinReal,
  205.                  MainMinImaginary,
  206.                  MainRealWidth,
  207.                  MainImaginaryHeight,
  208.  
  209.                  LastSize,
  210.                  LastMinReal,
  211.                  LastMinImaginary;
  212.  
  213.     /* Size and position of the screen. */
  214.  
  215. UWORD                 AreaLeft,
  216.                  AreaTop,
  217.                  AreaWidth,
  218.                  AreaHeight;
  219.  
  220.     /* Various flags. */
  221.  
  222. BYTE                 Running    = FALSE,
  223.                  NewCoords    = FALSE,
  224.                  AreaActive    = FALSE,
  225.                  GotClip    = FALSE,
  226.                  NewMode    = FALSE,
  227.                  Frame        = FALSE,
  228.                  Include    = TRUE,
  229.                  Faster        = TRUE,
  230.                  Precise    = FALSE,
  231.                  HoldIt        = FALSE,
  232.                  AnimRunning    = FALSE,
  233.                  FullPicture;
  234.  
  235.     /* Animation creation interface. */
  236.  
  237. struct AnimInfo            *AnimInfo;
  238.  
  239.     /* A range of colour intensities and the colour transition table. */
  240.  
  241. UBYTE                *Wave,
  242.                 *Range;
  243. struct Palette            *Palette;
  244.  
  245.     /* The levels of the palette colour sliders. */
  246.  
  247. UBYTE                 RedLevel    = 27,
  248.                  GreenLevel    = 22,
  249.                  BlueLevel    = 17;
  250.  
  251. BYTE                 LevelPatched    = FALSE;
  252.  
  253.     /* Rendering data. */
  254.  
  255. LONG                  Mode        = LORES_KEY,
  256.                  Depth        = 5,
  257.                  Square        = 256;
  258.  
  259.     /* The TextFont structure contained in Font.c */
  260.  
  261. extern struct TextFont         DigitFont;
  262.  
  263.     /* A single line bitmap whose planes are to be located
  264.      * in fast ram.
  265.      */
  266.  
  267. struct BitMap             LineBitMap;
  268.  
  269.     /* Current drawing pen colour. */
  270.  
  271. ULONG                 CurrentPen;
  272.  
  273.     /* Global image data. */
  274.  
  275. struct BitMap            *GlobalBitMap;
  276. ULONG                 GlobalMode;
  277. LONG                 GlobalDepth,
  278.                  GlobalSize;
  279. struct Palette            *GlobalPalette;
  280.  
  281.     /* Compatibility data. */
  282.  
  283. BYTE                 IsNative,
  284.                  UseDouble,
  285.                  Is39;
  286. UWORD                 MaxRange,
  287.                  PaletteSize;
  288.  
  289.     /* The standard font to be use throughout the
  290.      * whole program.
  291.      */
  292.  
  293. struct TextAttr DefaultFont =
  294. {
  295.     (UBYTE *)"topaz.font",
  296.     8,
  297.     FS_NORMAL,
  298.     FPF_ROMFONT
  299. };
  300.  
  301.     /* Error codes as returned by ValidateAnim(). */
  302.  
  303. STRPTR AnimErrors[] =
  304. {
  305.     NULL,
  306.  
  307.     "Invalid anim sequence",
  308.     "Could not find body",
  309.     "Unsupported anim op.",
  310.     "Could not find frames",
  311.     "Unsupported masking op.",
  312.     "Invalid picture",
  313.     "Unsupported compr. op.",
  314.     "Could not find header",
  315.     "Picture has wrong size",
  316.     "Picture has wrong display mode"
  317. };
  318.  
  319.     /* Definitions for the pull-down menu used by the program. */
  320.  
  321. struct NewMenu MandelbrotMenu[] =
  322. {
  323.     { NM_TITLE, "Project",             0 , 0,            0,    (APTR)0},
  324.     {  NM_ITEM, "Open picture...",        "O", 0,            0,    (APTR)MEN_OPEN},
  325.     {  NM_ITEM, "Save picture",         0 , 0,            0,    (APTR)MEN_SAVE},
  326.     {  NM_ITEM, "Save picture as...",    "S", 0,            0,    (APTR)MEN_SAVEAS},
  327.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  328.     {  NM_ITEM, "Priority",             0 , 0,            0,    (APTR)0},
  329.     {   NM_SUB, "-5",             0 , CHECKIT|MENUTOGGLE,~1,    (APTR)MEN_PRI0},
  330.     {   NM_SUB, " 0",             0 , CHECKIT|CHECKED|MENUTOGGLE,~2,    (APTR)MEN_PRI1},
  331.     {   NM_SUB, "+5",             0 , CHECKIT|MENUTOGGLE,~4,    (APTR)MEN_PRI2},
  332.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  333.     {  NM_ITEM, "Replay animation...",    "!", 0,            0,    (APTR)MEN_PLAY},
  334.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  335.     {  NM_ITEM, "Begin animation...",    "B", 0,            0,    (APTR)MEN_START},
  336.     {  NM_ITEM, "End animation",        "E", 0,            0,    (APTR)MEN_STOP},
  337.     {  NM_ITEM, "Set scroll amount...",    "A", 0,            0,    (APTR)MEN_SCROLL},
  338.     {  NM_ITEM, "Include frame",         0 , CHECKIT|MENUTOGGLE,0,    (APTR)MEN_FRAME},
  339.     {  NM_ITEM, "Include coordinates",     0 , CHECKIT|CHECKED|MENUTOGGLE,0,    (APTR)MEN_INCLUDE},
  340.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  341.     {  NM_ITEM, "Change resolution",    "X", 0,            0,    (APTR)MEN_RESOLUTION},
  342.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  343.     {  NM_ITEM, "About...",            "?", 0,            0,    (APTR)MEN_ABOUT},
  344.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  345.     {  NM_ITEM, "Quit...",            "Q", 0,            0,    (APTR)MEN_QUIT},
  346.  
  347.     { NM_TITLE, "Calculation",         0 , 0,            0,    (APTR)0},
  348.     {  NM_ITEM, "Magnify...",        "M", 0,            0,    (APTR)MEN_ZOOM},
  349.     {  NM_ITEM, "Detail...",        "D", 0,            0,    (APTR)MEN_CLIP},
  350.     {  NM_ITEM, "Recalculate...",        "R", 0,            0,    (APTR)MEN_RERUN},
  351.     {  NM_ITEM, "Precise calculation",     0 , CHECKIT|MENUTOGGLE,0,    (APTR)MEN_PRECISE},
  352.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  353.     {  NM_ITEM, "Coordinates...",        "C", 0,            0,    (APTR)MEN_COORDS},
  354.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  355.     {  NM_ITEM, "Palette...",        "P", 0,            0,    (APTR)MEN_PALETTE},
  356.     {  NM_ITEM, NM_BARLABEL,         0 , 0,            0,    (APTR)0},
  357.     {  NM_ITEM, "Toggle calculation",    ".", 0,            0,    (APTR)MEN_RUN},
  358.  
  359.     { NM_TITLE, "Depth",             0 , 0,            0,    (APTR)0},
  360.     {  NM_ITEM, "   32",            "0", CHECKIT|CHECKED,    ~  1,    (APTR)5},
  361.     {  NM_ITEM, "   64",            "1", CHECKIT,        ~  2,    (APTR)6},
  362.     {  NM_ITEM, "  128",            "2", CHECKIT,        ~  4,    (APTR)7},
  363.     {  NM_ITEM, "  256",            "3", CHECKIT,        ~  8,    (APTR)8},
  364.     {  NM_ITEM, "  512",            "4", CHECKIT,        ~ 16,    (APTR)9},
  365.     {  NM_ITEM, " 1024",            "5", CHECKIT,        ~ 32,    (APTR)10},
  366.     {  NM_ITEM, " 2048",            "6", CHECKIT,        ~ 64,    (APTR)11},
  367.     {  NM_ITEM, " 4096",            "7", CHECKIT,        ~128,    (APTR)12},
  368.     {  NM_ITEM, " 8192",            "8", CHECKIT,        ~256,    (APTR)13},
  369.     {  NM_ITEM, "16384",            "9", CHECKIT,        ~512,    (APTR)14},
  370.     {   NM_END, 0,                 0 , 0,            0,    (APTR)0}
  371. };
  372.  
  373.     /* Run-dump of the stopwatch mouse pointer. */
  374.  
  375. UWORD __chip Stopwatch[(2 + 16) * 2] =
  376. {
  377.     0x0000,0x0000,
  378.  
  379.     0x0400,0x07C0,
  380.     0x0000,0x07C0,
  381.     0x0100,0x0380,
  382.     0x0000,0x07E0,
  383.     0x07C0,0x1FF8,
  384.     0x1FF0,0x3FEC,
  385.     0x3FF8,0x7FDE,
  386.     0x3FF8,0x7FBE,
  387.     0x7FFC,0xFF7F,
  388.     0x7EFC,0xFFFF,
  389.     0x7FFC,0xFFFF,
  390.     0x3FF8,0x7FFE,
  391.     0x3FF8,0x7FFE,
  392.     0x1FF0,0x3FFC,
  393.     0x07C0,0x1FF8,
  394.     0x0000,0x07E0,
  395.  
  396.     0x0000,0x0000
  397. };
  398.  
  399.     /* Definitions for a clear sprite. */
  400.  
  401. UWORD __chip ClearData[(2 + 1) * 2] =
  402. {
  403.     0x0000,0x0000,
  404.  
  405.     0x0000,0x0000,
  406.  
  407.     0x0000,0x0000
  408. };
  409.  
  410.     /* Run-dump of the picture icon image data. */
  411.  
  412. USHORT Picture1Data[700] =
  413. {
  414.     0x0000,0x0000,0x0000,0x0000,0x0010,0x0000,0x0000,0x0000,
  415.     0x0000,0x0030,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000,
  416.     0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0000,
  417.     0x0030,0x0000,0x0000,0x0000,0x4000,0x0030,0x0000,0x0000,
  418.     0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0400,0x0030,
  419.     0x0000,0x0000,0x0000,0x1C00,0x0030,0x0000,0x0000,0x0000,
  420.     0x0000,0x0030,0x0000,0x0000,0x0000,0x4800,0x0030,0x0000,
  421.     0x0000,0x0000,0xC000,0x0030,0x0000,0x0000,0x0005,0x8000,
  422.     0x0030,0x0000,0x0000,0x0001,0x0300,0x0030,0x0000,0x0000,
  423.     0x0001,0x0200,0x0030,0x0000,0x0000,0x0001,0x0200,0x0030,
  424.     0x0000,0x0000,0x0100,0x0020,0x0030,0x0000,0x0000,0x002F,
  425.     0x8E80,0x8030,0x0000,0x0000,0x0328,0x0080,0x0030,0x0000,
  426.     0x0000,0x0260,0x002E,0xC030,0x0000,0x0000,0x0200,0x0008,
  427.     0x8030,0x0000,0x0000,0x0200,0x0000,0x8030,0x0000,0x0000,
  428.     0x1600,0x0000,0x0030,0x0000,0x0000,0x1400,0x0000,0x8030,
  429.     0x0000,0x2000,0x1000,0x0000,0x0030,0x0000,0x0040,0x3000,
  430.     0x0000,0x9030,0x0000,0x4000,0x2000,0x0000,0x3030,0x0000,
  431.     0x0080,0x6000,0x0000,0x6030,0x0000,0x0FB0,0x4000,0x0000,
  432.     0x0030,0x0000,0x0800,0xC000,0x0000,0x2030,0x0000,0x0800,
  433.     0x0000,0x0000,0x6030,0x0000,0x1800,0xC000,0x0000,0x4030,
  434.     0x0000,0x3000,0x8000,0x0000,0x4030,0x0001,0x2000,0x8000,
  435.     0x0000,0xC030,0x0003,0x6000,0x0000,0x0000,0x8030,0x0F82,
  436.     0x0000,0x0000,0x0001,0x0030,0x0020,0x0000,0x0000,0x0000,
  437.     0x0030,0x0008,0x0000,0x0000,0x0000,0x0030,0x0000,0x2000,
  438.     0x0000,0x0000,0x0030,0x0003,0x8000,0x8000,0x0000,0x4030,
  439.     0x0006,0x0000,0x8000,0x0000,0x4030,0x0000,0x4800,0x0000,
  440.     0x0000,0x0030,0x0000,0x0802,0x4000,0x0000,0x2030,0x0000,
  441.     0x0006,0x4000,0x0000,0x6030,0x0000,0x060C,0x0000,0x0000,
  442.     0x0030,0x0000,0x3C78,0x0000,0x0000,0x0030,0x0000,0x20C0,
  443.     0x0000,0x0000,0x1030,0x0000,0x2000,0x1800,0x0000,0xF030,
  444.     0x0000,0x4000,0x0000,0x0001,0x8030,0x0000,0x0000,0x2000,
  445.     0x0001,0x0030,0x0000,0x0000,0x0200,0x0000,0x0030,0x0000,
  446.     0x0000,0x0200,0x0000,0x0030,0x0000,0x0000,0x0200,0x0000,
  447.     0x4030,0x0000,0x0000,0x0080,0x003E,0xC030,0x0000,0x0000,
  448.     0x0180,0x0120,0x8030,0x0000,0x0000,0x0D19,0x8360,0x8030,
  449.     0x0000,0x0000,0x0101,0x0200,0x0030,0x0000,0x0000,0x0001,
  450.     0x0200,0x0030,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000,
  451.     0x0000,0x0000,0x0300,0x0030,0x0000,0x0000,0x0005,0x0E00,
  452.     0x0030,0x0000,0x0000,0x0001,0x1800,0x0030,0x0000,0x0000,
  453.     0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x2000,0x0030,
  454.     0x0000,0x0000,0x0000,0x2C00,0x0030,0x0000,0x0000,0x0000,
  455.     0x2000,0x0030,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000,
  456.     0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0000,
  457.     0x0030,0x7FFF,0xFFFF,0xFFFF,0xFFFF,0xFFF0,
  458.  
  459.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFE0,0xD555,0x5555,0x5555,
  460.     0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,0x5540,0xD555,
  461.     0x5555,0x5555,0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,
  462.     0x5540,0xD555,0x5555,0x5555,0x1555,0x5540,0xD555,0x5555,
  463.     0x5555,0x3555,0x5540,0xD555,0x5555,0x5555,0x8155,0x5540,
  464.     0xD555,0x5555,0x5555,0x8155,0x5540,0xD555,0x5555,0x5557,
  465.     0x0555,0x5540,0xD555,0x5555,0x555C,0x0555,0x5540,0xD555,
  466.     0x5555,0x5550,0x0155,0x5540,0xD555,0x5555,0x5558,0x5155,
  467.     0x5540,0xD555,0x5555,0x5558,0x5855,0x5540,0xD555,0x5555,
  468.     0x7558,0x59D5,0x5540,0xD555,0x5555,0x6DF8,0x7197,0x5540,
  469.     0xD555,0x5555,0x6080,0x401E,0x5540,0xD555,0x5555,0x4000,
  470.     0x5010,0x5540,0xD555,0x5555,0x5015,0x5500,0x5540,0xD555,
  471.     0x5555,0x5115,0x5540,0x1540,0xD555,0x5555,0xF155,0x5554,
  472.     0x5540,0xD555,0x5555,0x8155,0x5551,0x5540,0xD555,0xD555,
  473.     0x8155,0x5554,0x5540,0xD555,0x1555,0x8155,0x5556,0x5540,
  474.     0xD555,0x9755,0x8555,0x5554,0x1540,0xD555,0x1E35,0x0555,
  475.     0x5555,0x0540,0xD555,0x0005,0x1555,0x5555,0x0540,0xD555,
  476.     0x4005,0x1555,0x5555,0x1540,0xD555,0xC040,0x1555,0x5555,
  477.     0x1540,0xD555,0x0550,0x1555,0x5555,0x1540,0xD555,0x8554,
  478.     0x5555,0x5555,0x1540,0xD55B,0x8556,0x1555,0x5557,0x1540,
  479.     0xD558,0x0554,0x5555,0x5556,0x1540,0xFFF0,0x1555,0x5555,
  480.     0x5554,0x1540,0xC000,0x1555,0x5555,0x555D,0x5540,0xD001,
  481.     0x5555,0x5555,0x5550,0x5540,0xD541,0xD555,0x5555,0x5555,
  482.     0x5540,0xD550,0x1557,0x5555,0x5554,0x5540,0xD558,0x1556,
  483.     0x5555,0x5555,0x5540,0xD550,0x1556,0x5555,0x5555,0x1540,
  484.     0xD551,0x055C,0x5555,0x5555,0x1540,0xD555,0x05F0,0x5555,
  485.     0x5555,0x9540,0xD555,0x4580,0x1555,0x5555,0x1540,0xD555,
  486.     0xC000,0x1555,0x5555,0x1540,0xD555,0x8001,0x1555,0x5555,
  487.     0x9540,0xD555,0x0005,0x1555,0x5557,0x1540,0xD555,0x1515,
  488.     0x8555,0x5556,0x0540,0xD555,0x5555,0x8555,0x555C,0x0540,
  489.     0xD555,0x1555,0x0555,0x5550,0x5540,0xD555,0x5555,0x4155,
  490.     0x5574,0x5540,0xD555,0x5555,0x5155,0x5564,0x5540,0xD555,
  491.     0x5555,0x7155,0x55C6,0x5540,0xD555,0x5555,0x403D,0x5F80,
  492.     0x1540,0xD555,0x5555,0x7001,0x5800,0x1540,0xD555,0x5555,
  493.     0x4040,0x5014,0x5540,0xD555,0x5555,0x5040,0x5015,0x5540,
  494.     0xD555,0x5555,0x5458,0x5955,0x5540,0xD555,0x5555,0x5558,
  495.     0x5955,0x5540,0xD555,0x5555,0x5558,0x7155,0x5540,0xD555,
  496.     0x5555,0x5550,0x6055,0x5540,0xD555,0x5555,0x5550,0x0155,
  497.     0x5540,0xD555,0x5555,0x5554,0x0555,0x5540,0xD555,0x5555,
  498.     0x5555,0x8555,0x5540,0xD555,0x5555,0x5555,0x8555,0x5540,
  499.     0xD555,0x5555,0x5555,0x1155,0x5540,0xD555,0x5555,0x5555,
  500.     0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,0x5540,0xD555,
  501.     0x5555,0x5555,0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,
  502.     0x5540,0x8000,0x0000,0x0000,0x0000,0x0000
  503. };
  504.  
  505.     /* Definitions for the picture icon image. */
  506.  
  507. struct Image Picture1Image =
  508. {
  509.     0,0,
  510.     76,70,2,
  511.     (USHORT *)&Picture1Data[0],
  512.     0x03,0x00,
  513.     (struct Image *)NULL
  514. };
  515.  
  516.     /* Tool types for the picture project icon. */
  517.  
  518. char *PictureToolTypes[] =
  519. {
  520.     "FILETYPE=ILBM",
  521.     NULL
  522. };
  523.  
  524.     /* The name of the project's default tool (will be filled
  525.      * in later).
  526.      */
  527.  
  528. UBYTE DefaultTool[256];
  529.  
  530.     /* Definitions for the picture project icon. */
  531.  
  532. struct DiskObject PictureIcon =
  533. {
  534.     WB_DISKMAGIC,
  535.     WB_DISKVERSION,
  536.  
  537.     (struct Gadget *)NULL,
  538.     0,0,
  539.     76,70,
  540.     0x0004,
  541.     0x0003,
  542.     0x0001,
  543.     (APTR)&Picture1Image,
  544.     (APTR)NULL,
  545.     (struct IntuiText *)NULL,
  546.     NULL,
  547.     (APTR)NULL,
  548.     NULL,
  549.     (APTR)NULL,
  550.  
  551.     WBPROJECT,
  552.     (char *)NULL,
  553.     PictureToolTypes,
  554.     NO_ICON_POSITION,
  555.     NO_ICON_POSITION,
  556.     (struct DrawerData *)NULL,
  557.     (char *)NULL,
  558.     20000
  559. };
  560.  
  561.     /* Run-dump of the anim icon image data. */
  562.  
  563. UWORD Anim1Data[700] =
  564. {
  565.     0x0000,0x0000,0x0000,0x0000,0x0010,0x0000,0x0000,0x0000,
  566.     0x0000,0x0030,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000,
  567.     0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0000,
  568.     0x0030,0x0000,0x0000,0x0000,0x4000,0x0030,0x0000,0x0000,
  569.     0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0400,0x0030,
  570.     0x0000,0x0000,0x0000,0x1C00,0x0030,0x0000,0x0000,0x0000,
  571.     0x0000,0x0030,0x0000,0x0000,0x0000,0x4800,0x0030,0x0000,
  572.     0x0000,0x0000,0xC000,0x0030,0x0000,0x0000,0x0005,0x8000,
  573.     0x0030,0x0000,0x0000,0x0001,0x0300,0x0030,0x0000,0x0000,
  574.     0x0001,0x0200,0x0030,0x0000,0x0000,0x0001,0x0200,0x0030,
  575.     0x0000,0x0000,0x0100,0x0020,0x0030,0x0000,0x0000,0x002F,
  576.     0x8E80,0x8030,0x0000,0x0000,0x0328,0x0080,0x0030,0x0000,
  577.     0x0000,0x0260,0x002E,0xC030,0x0003,0xFFD0,0x0200,0x0008,
  578.     0x8030,0x0002,0x0010,0x0200,0x0000,0x8030,0x0002,0x0010,
  579.     0x1600,0x0000,0x0030,0x0002,0x0010,0x1400,0x0000,0x8030,
  580.     0x0002,0x2010,0x1000,0x0000,0x0030,0x0002,0x0010,0x3000,
  581.     0x0000,0x9030,0x0002,0x4010,0x2000,0x0000,0x3030,0x0002,
  582.     0x0010,0x6000,0x0000,0x6030,0x0002,0x0F10,0x4000,0x0000,
  583.     0x0030,0x0002,0x0810,0xC000,0x0000,0x2030,0x0002,0x0810,
  584.     0x0000,0x0000,0x6030,0x0002,0x0010,0xC000,0x0000,0x4030,
  585.     0x0000,0x0010,0x8000,0x0000,0x4030,0x0003,0xFFF0,0x8000,
  586.     0x0000,0xC030,0x0003,0x6000,0x0000,0x0000,0x8030,0x0F82,
  587.     0x0000,0x0000,0x0001,0x0030,0x0020,0x0000,0x0000,0x0000,
  588.     0x0030,0x0008,0x0000,0x0000,0x0000,0x0030,0x0000,0x2000,
  589.     0x0000,0x0000,0x0030,0x0003,0x8000,0x8000,0x0000,0x4030,
  590.     0x0006,0x0000,0x8000,0x0000,0x4030,0x0000,0x4800,0x0000,
  591.     0x0000,0x0030,0x0000,0x0802,0x4000,0x0000,0x2030,0x0000,
  592.     0x0006,0x4000,0x0000,0x6030,0x0000,0x060C,0x0000,0x0000,
  593.     0x0030,0x0000,0x3C78,0x0000,0x0000,0x0030,0x0000,0x20C0,
  594.     0x0000,0x0000,0x1030,0x0000,0x2000,0x1800,0x0000,0xF030,
  595.     0x0000,0x400C,0x0000,0x0C01,0x8030,0x0000,0x001C,0x2000,
  596.     0x1E01,0x0030,0x0000,0x001C,0x0200,0x0C00,0x0030,0x0000,
  597.     0x001E,0x0200,0x0000,0x0030,0x0000,0x003E,0x0DF0,0x7C1F,
  598.     0xF830,0x0000,0x003E,0x0FF8,0xFC1F,0xFC30,0x0000,0x0037,
  599.     0x0F18,0x0D1D,0xCC30,0x0000,0x0073,0x0E19,0x8D59,0xCC30,
  600.     0x0000,0x0073,0x0E19,0x0C19,0xCC30,0x0000,0x0063,0x8C19,
  601.     0x0C19,0xCC30,0x0000,0x00E1,0x8C18,0x0C19,0xCC30,0x0000,
  602.     0x00FF,0x8C18,0x0D19,0xCC30,0x0000,0x00FF,0xCC19,0x0C19,
  603.     0xCC30,0x0000,0x01C1,0xCC19,0x0C19,0xCC30,0x0000,0x01C0,
  604.     0xCC18,0x0C19,0xCC30,0x0000,0x0180,0xEC18,0x2C19,0xCC30,
  605.     0x0000,0x0180,0xEC18,0x2C19,0xCC30,0x0000,0x0100,0x6C18,
  606.     0x2C18,0x8C30,0x0000,0x0000,0x0000,0x0000,0x0030,0x0000,
  607.     0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,0x0000,0x0000,
  608.     0x0030,0x7FFF,0xFFFF,0xFFFF,0xFFFF,0xFFF0,
  609.  
  610.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFE0,0xD555,0x5555,0x5555,
  611.     0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,0x5540,0xD555,
  612.     0x5555,0x5555,0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,
  613.     0x5540,0xD555,0x5555,0x5555,0x1555,0x5540,0xD555,0x5555,
  614.     0x5555,0x3555,0x5540,0xD555,0x5555,0x5555,0x8155,0x5540,
  615.     0xD555,0x5555,0x5555,0x8155,0x5540,0xD555,0x5555,0x5557,
  616.     0x0555,0x5540,0xD555,0x5555,0x555C,0x0555,0x5540,0xD555,
  617.     0x5555,0x5550,0x0155,0x5540,0xD555,0x5555,0x5558,0x5155,
  618.     0x5540,0xD555,0x5555,0x5558,0x5855,0x5540,0xD555,0x5555,
  619.     0x7558,0x59D5,0x5540,0xD555,0x5555,0x6DF8,0x7197,0x5540,
  620.     0xD555,0x5555,0x6080,0x401E,0x5540,0xD555,0x5555,0x4000,
  621.     0x5010,0x5540,0xD55F,0xFFC5,0x5015,0x5500,0x5540,0xD558,
  622.     0x0005,0x5115,0x5540,0x1540,0xD558,0x0005,0xF155,0x5554,
  623.     0x5540,0xD559,0x5545,0x8155,0x5551,0x5540,0xD559,0xD545,
  624.     0x8155,0x5554,0x5540,0xD559,0x1545,0x8155,0x5556,0x5540,
  625.     0xD559,0x9745,0x8555,0x5554,0x1540,0xD559,0x1E45,0x0555,
  626.     0x5555,0x0540,0xD559,0x0045,0x1555,0x5555,0x0540,0xD559,
  627.     0x4045,0x1555,0x5555,0x1540,0xD559,0xC040,0x1555,0x5555,
  628.     0x1540,0xD559,0x0540,0x1555,0x5555,0x1540,0xD559,0x8544,
  629.     0x5555,0x5555,0x1540,0xD559,0xFFC6,0x1555,0x5557,0x1540,
  630.     0xD550,0x0004,0x5555,0x5556,0x1540,0xFFF0,0x0005,0x5555,
  631.     0x5554,0x1540,0xC000,0x1555,0x5555,0x555D,0x5540,0xD001,
  632.     0x5555,0x5555,0x5550,0x5540,0xD541,0xD555,0x5555,0x5555,
  633.     0x5540,0xD550,0x1557,0x5555,0x5554,0x5540,0xD558,0x1556,
  634.     0x5555,0x5555,0x5540,0xD550,0x1556,0x5555,0x5555,0x1540,
  635.     0xD551,0x055C,0x5555,0x5555,0x1540,0xD555,0x05F0,0x5555,
  636.     0x5555,0x9540,0xD555,0x4580,0x1555,0x5555,0x1540,0xD555,
  637.     0xC000,0x1555,0x5555,0x1540,0xD555,0x8001,0x1555,0x5555,
  638.     0x9540,0xD555,0x0005,0x1555,0x5557,0x1540,0xD555,0x1515,
  639.     0x8555,0x5556,0x0540,0xD555,0x5551,0x8555,0x515C,0x0540,
  640.     0xD555,0x1545,0x0555,0x4150,0x5540,0xD555,0x5551,0x4155,
  641.     0x5274,0x5540,0xD555,0x5551,0x5155,0x4D64,0x5540,0xD555,
  642.     0x5542,0x7005,0x01C0,0x0540,0xD555,0x5528,0x4D15,0x7D9C,
  643.     0xC140,0xD555,0x5528,0x6248,0x8002,0x1140,0xD555,0x5505,
  644.     0x4100,0x0005,0x0140,0xD555,0x5550,0x4040,0x4001,0x4140,
  645.     0xD555,0x5550,0x4240,0x4141,0x4140,0xD555,0x5502,0x8140,
  646.     0x4141,0x4140,0xD555,0x54A0,0x0140,0x6141,0x4140,0xD555,
  647.     0x5480,0x0140,0x6041,0x4140,0xD555,0x543F,0x4140,0x0141,
  648.     0x4140,0xD555,0x5501,0x0140,0x0141,0x4140,0xD555,0x5554,
  649.     0x0141,0x8141,0x4140,0xD555,0x5414,0xA141,0x8141,0x4140,
  650.     0xD555,0x5414,0x8141,0x0141,0x4140,0xD555,0x5555,0x6D59,
  651.     0x4D58,0x8D40,0xD555,0x5455,0x1145,0x5145,0x5140,0xD555,
  652.     0x5555,0x5555,0x5555,0x5540,0xD555,0x5555,0x5555,0x5555,
  653.     0x5540,0x8000,0x0000,0x0000,0x0000,0x0000
  654. };
  655.  
  656.     /* Definitions for the anim icon image. */
  657.  
  658. struct Image Anim1Image =
  659. {
  660.     0,0,
  661.     76,70,2,
  662.     (UWORD *)&Anim1Data[0],
  663.     0x03,0x00,
  664.     (struct Image *)NULL
  665. };
  666.  
  667.     /* Tool types for the anim project icon. */
  668.  
  669. char *AnimToolTypes[] =
  670. {
  671.     "FILETYPE=ANIM|ILBM",
  672.     NULL
  673. };
  674.  
  675.     /* Definitions for the anim project icon. */
  676.  
  677. struct DiskObject AnimIcon =
  678. {
  679.     WB_DISKMAGIC,
  680.     WB_DISKVERSION,
  681.  
  682.     (struct Gadget *)NULL,
  683.     23,15,
  684.     76,70,
  685.     0x0004,
  686.     0x0003,
  687.     0x0001,
  688.     (APTR)&Anim1Image,
  689.     (APTR)NULL,
  690.     (struct IntuiText *)NULL,
  691.     NULL,
  692.     (APTR)NULL,
  693.     NULL,
  694.     (APTR)NULL,
  695.  
  696.     WBPROJECT,
  697.     (char *)NULL,
  698.     AnimToolTypes,
  699.     NO_ICON_POSITION,
  700.     NO_ICON_POSITION,
  701.     (struct DrawerData *)NULL,
  702.     (char *)NULL,
  703.     20000
  704. };
  705.  
  706.     /* Iterate(double RealValue,double ImaginaryValue):
  707.      *
  708.      *    The routine to handle the final calculation.
  709.      */
  710. /*
  711. UBYTE __inline
  712. Iterate(double RealValue,double ImaginaryValue)
  713. {
  714.     double    Real        = RealValue,        RealTemp,
  715.         Imaginary    = ImaginaryValue,    ImaginaryTemp;
  716.     WORD    i        = 1;
  717.  
  718.     do
  719.     {
  720.         RealTemp    = Real * Real;
  721.         ImaginaryTemp    = Imaginary * Imaginary;
  722.  
  723.         if(fabs(RealTemp + ImaginaryTemp) > 4.0)
  724.             return(Wave[i]);
  725.         else
  726.         {
  727.             Imaginary    = (Real + Real) * Imaginary + ImaginaryValue;
  728.             Real        = RealTemp - ImaginaryTemp + RealValue;
  729.         }
  730.     }
  731.     while(++i <= MaxIteration);
  732.  
  733.     return(0);
  734. }
  735. */
  736.     /* SetWait(struct Window *Window):
  737.      *
  738.      *    Attach a busy wait mouse pointer to a window.
  739.      */
  740.  
  741. VOID
  742. SetWait(struct Window *Window)
  743. {
  744.     if(Is39)
  745.     {
  746.         SetWindowPointer(Window,
  747.             WA_BusyPointer,        TRUE,
  748.             WA_PointerDelay,    TRUE,
  749.         TAG_DONE);
  750.     }
  751.     else
  752.         SetPointer(Window,Stopwatch,16,16,-6,0);
  753. }
  754.  
  755.     /* ClrWait(struct Window *Window):
  756.      *
  757.      *    Remove the busy wait mouse pointer from a window.
  758.      */
  759.  
  760. VOID
  761. ClrWait(struct Window *Window)
  762. {
  763.     if(Is39)
  764.         SetWindowPointer(Window,TAG_DONE);
  765.     else
  766.         ClearPointer(Window);
  767. }
  768.  
  769.     /* CycleColours(BYTE Forward):
  770.      *
  771.      *    Tiny subroutine, handles the actual colour cycling.
  772.      */
  773.  
  774. VOID __regargs
  775. CycleColours(BYTE Forward)
  776. {
  777.     if(Forward)
  778.     {
  779.         ULONG    Size,
  780.             Top,
  781.             i;
  782.  
  783.         Size = GetPaletteSize(Palette);
  784.  
  785.         Top = GetPaletteEntry(Palette,Size - 1);
  786.  
  787.         for(i = Size - 1 ; i > 2 ; i--)
  788.             SetPaletteEntry(Palette,GetPaletteEntry(Palette,i - 1),i);
  789.  
  790.         SetPaletteEntry(Palette,Top,2);
  791.     }
  792.     else
  793.     {
  794.         ULONG    Bottom,
  795.             Size,
  796.             i;
  797.  
  798.         Size = GetPaletteSize(Palette);
  799.  
  800.         Bottom = GetPaletteEntry(Palette,2);
  801.  
  802.         for(i = 2 ; i < Size - 1 ; i++)
  803.             SetPaletteEntry(Palette,GetPaletteEntry(Palette,i + 1),i);
  804.  
  805.         SetPaletteEntry(Palette,Bottom,Size - 1);
  806.     }
  807.  
  808.     LoadPalette(Screen,Palette,0);
  809. }
  810.  
  811.     /* SetProperties(ULONG ID):
  812.      *
  813.      *    Queries the properties of a certain display mode and adjusts
  814.      *    the program parameters accordingly.
  815.      */
  816.  
  817. BYTE __regargs
  818. SetProperties(ULONG ID)
  819. {
  820.     struct DisplayInfo DisplayInfo;
  821.  
  822.         /* Query the properties... */
  823.  
  824.     if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,ID))
  825.     {
  826.             /* More information available? */
  827.  
  828.         if(Is39)
  829.         {
  830.                 /* Does this mode support double-bufferin? */
  831.  
  832.             if(DisplayInfo . PropertyFlags & DIPF_IS_DBUFFER)
  833.                 UseDouble = TRUE;
  834.             else
  835.                 UseDouble = FALSE;
  836.  
  837.                 /* Is this a native Amiga display mode? */
  838.  
  839.             if(DisplayInfo . PropertyFlags & DIPF_IS_FOREIGN)
  840.                 IsNative = FALSE;
  841.             else
  842.                 IsNative = TRUE;
  843.  
  844.                 /* Determine maximum available colour range. */
  845.  
  846.             MaxRange = 8;
  847.  
  848.             if(DisplayInfo . RedBits < MaxRange)
  849.                 MaxRange = DisplayInfo . RedBits;
  850.  
  851.             if(DisplayInfo . GreenBits < MaxRange)
  852.                 MaxRange = DisplayInfo . GreenBits;
  853.  
  854.             if(DisplayInfo . BlueBits < MaxRange)
  855.                 MaxRange = DisplayInfo . BlueBits;
  856.  
  857.             MaxRange = 1 << MaxRange;
  858.         }
  859.         else
  860.         {
  861.             UseDouble    = TRUE;
  862.             IsNative    = TRUE;
  863.  
  864.             MaxRange    = 16;
  865.         }
  866.  
  867.         return(TRUE);
  868.     }
  869.     else
  870.         return(FALSE);
  871. }
  872.  
  873.     /* GetModeSize(ULONG ID):
  874.      *
  875.      *    Return the approriate screen size of a certain display mode.
  876.      */
  877.  
  878. LONG __regargs
  879. GetModeSize(ULONG ID)
  880. {
  881.     struct DimensionInfo DimensionInfo;
  882.  
  883.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  884.     {
  885.         LONG    ScanWidth,
  886.             ScanHeight,
  887.  
  888.             Width    = 4,
  889.             Height    = 4;
  890.  
  891.         ScanWidth    = DimensionInfo . StdOScan . MaxX - DimensionInfo . StdOScan . MinX + 1;
  892.         ScanHeight    = DimensionInfo . StdOScan . MaxY - DimensionInfo . StdOScan . MinY + 1;
  893.  
  894.         while(Width < ScanWidth)
  895.             Width *= 2;
  896.  
  897.         if(Width > ScanWidth)
  898.             Width /= 2;
  899.  
  900.         while(Height < ScanHeight)
  901.             Height *= 2;
  902.  
  903.         if(Height > ScanHeight)
  904.             Height /= 2;
  905.  
  906.         if(Height < Width)
  907.             Width = Height;
  908.  
  909.         if(Width < 256 || Width < DimensionInfo . MinRasterWidth || Height < DimensionInfo . MinRasterHeight)
  910.             return(0);
  911.         else
  912.             return(Width);
  913.     }
  914.     else
  915.         return(0);
  916. }
  917.  
  918.     /* ModeFilter(register __a1 ULONG ID):
  919.      *
  920.      *    Called by SelectDisplayMode(), filters out unapproriate display mode IDs.
  921.      */
  922.  
  923. LONG __saveds __asm
  924. ModeFilter(register __a1 ULONG ID)
  925. {
  926.     struct DimensionInfo    DimensionInfo;
  927.     LONG            Result = TRUE;
  928.  
  929.     if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
  930.     {
  931.             /* Minimum are 4 bitplanes. */
  932.  
  933.         if(DimensionInfo . MaxDepth < 4)
  934.             Result = FALSE;
  935.  
  936.         if(Result)
  937.         {
  938.                 /* Does the screen size fit? */
  939.  
  940.             if(!GetModeSize(ID))
  941.                 Result = FALSE;
  942.         }
  943.     }
  944.  
  945.     if(Result)
  946.     {
  947.         struct DisplayInfo DisplayInfo;
  948.  
  949.         if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,ID))
  950.         {
  951.                 /* 4096 colours are minimum. */
  952.  
  953.             if(DisplayInfo . PaletteRange < 4096)
  954.                 Result = FALSE;
  955.  
  956.             if(Is39)
  957.             {
  958.                     /* Only eight bits per component are supported so far. */
  959.  
  960.                 if(DisplayInfo . RedBits > 8 || DisplayInfo . GreenBits > 8 || DisplayInfo . BlueBits > 8)
  961.                     Result = FALSE;
  962.             }
  963.         }
  964.  
  965.         if(Result)
  966.         {
  967.             if(DisplayInfo . Resolution . x)
  968.             {
  969.                     /* The display aspect ration should be 1:1. */
  970.  
  971.                 if(DisplayInfo . Resolution . y / DisplayInfo . Resolution . x > 1)
  972.                     Result = FALSE;
  973.             }
  974.         }
  975.     }
  976.  
  977.     return(Result);
  978. }
  979.  
  980.     /* SelectDisplayMode(struct Window *Window,ULONG *Mode):
  981.      *
  982.      *    Select a new screen display mode.
  983.      */
  984.  
  985. BYTE __regargs
  986. SelectDisplayMode(struct Window *Window,ULONG *Mode)
  987. {
  988.     struct ScreenModeRequester    *Request;
  989.     struct Hook             FilterHook;
  990.     BYTE                 Result = FALSE;
  991.  
  992.     FilterHook . h_Entry    = ModeFilter;
  993.     FilterHook . h_SubEntry    = NULL;
  994.     FilterHook . h_Data    = NULL;
  995.  
  996.     if(Request = (struct ScreenModeRequester *)AllocAslRequestTags(ASL_ScreenModeRequest,
  997.         ASLSM_Window,        Window,
  998.         ASLSM_FilterFunc,    &FilterHook,
  999.         ASLSM_InitialDisplayID,    *Mode,
  1000.         ASLSM_PropertyFlags,    0,
  1001.         ASLSM_PropertyMask,    (DIPF_IS_HAM|DIPF_IS_DUALPF|DIPF_IS_PF2PRI|DIPF_IS_EXTRAHALFBRITE),
  1002.     TAG_DONE))
  1003.     {
  1004.         if(AslRequestTags(Request,TAG_DONE))
  1005.         {
  1006.             struct DimensionInfo DimensionInfo;
  1007.  
  1008.             if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Request -> sm_DisplayID))
  1009.             {
  1010.                 if(DimensionInfo . MaxDepth > 8)
  1011.                     Depth = 8;
  1012.                 else
  1013.                     Depth = DimensionInfo . MaxDepth;
  1014.  
  1015.                 *Mode = Request -> sm_DisplayID;
  1016.  
  1017.                 Result = TRUE;
  1018.             }
  1019.         }
  1020.  
  1021.         FreeAslRequest(Request);
  1022.     }
  1023.  
  1024.     return(Result);
  1025. }
  1026.  
  1027.     /* DrawSquare():
  1028.      *
  1029.      *    Draws a square rectangle at a given position.
  1030.      */
  1031.  
  1032. VOID __regargs
  1033. DrawSquare(struct RastPort *RPort,WORD X,WORD Y,WORD Width)
  1034. {
  1035.     Move(RPort,X,Y);
  1036.     Draw(RPort,X + Width - 1,Y);
  1037.     Draw(RPort,X + Width - 1,Y + Width - 1);
  1038.     Draw(RPort,X,Y + Width - 1);
  1039.     Draw(RPort,X,Y);
  1040. }
  1041.  
  1042.     /* DrawLine():
  1043.      *
  1044.      *    Draw a simple line from a to b.
  1045.      */
  1046.  
  1047. VOID __regargs
  1048. DrawLine(struct RastPort *RPort,UWORD FromX,UWORD FromY,UWORD ToX,UWORD ToY)
  1049. {
  1050.     Move(RPort,FromX,FromY);
  1051.     Draw(RPort,ToX,ToY);
  1052. }
  1053.  
  1054.     /* IterationSetup():
  1055.      *
  1056.      *    Sets up the iterations menu, checkmarks the currently
  1057.      *    selected number of iterations, uncheckmarks all the
  1058.      *    others.
  1059.      */
  1060.  
  1061. VOID
  1062. IterationSetup()
  1063. {
  1064.     struct MenuItem    *Item;
  1065.     WORD         i;
  1066.  
  1067.     ClearMenuStrip(Window);
  1068.  
  1069.     for(i = 0 ; i < 10 ; i++)
  1070.     {
  1071.         Item = ItemAddress(Menu,FULLMENUNUM(2,i,NOSUB));
  1072.  
  1073.         if((1 << (ULONG)GTMENUITEM_USERDATA(Item)) == MaxIteration + 1)
  1074.             Item -> Flags |= CHECKED;
  1075.         else
  1076.             Item -> Flags &= ~CHECKED;
  1077.     }
  1078.  
  1079.     ResetMenuStrip(Window,Menu);
  1080. }
  1081.  
  1082.     /* CycleServer():
  1083.      *
  1084.      *    The interrupt server routine which handles the
  1085.      *    colour cycling.
  1086.      */
  1087.  
  1088. VOID __saveds
  1089. CycleServer()
  1090. {
  1091.     struct MsgPort        *TimePort;
  1092.     struct timerequest    *TimeRequest;
  1093.     ULONG             Signals;
  1094.  
  1095.     if(TimePort = CreateMsgPort())
  1096.     {
  1097.         if(TimeRequest = CreateIORequest(TimePort,sizeof(struct timerequest)))
  1098.         {
  1099.             if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,NULL))
  1100.             {
  1101.                 Signal(ThisProcess,SIG_HANDSHAKE);
  1102.  
  1103.                 FOREVER
  1104.                 {
  1105.                     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1106.                     TimeRequest -> tr_time . tv_secs    = 0;
  1107.                     TimeRequest -> tr_time . tv_micro    = SECOND / 20;
  1108.  
  1109.                     SendIO(TimeRequest);
  1110.  
  1111.                     Signals = Wait(SIG_TIMER | SIG_KILL);
  1112.  
  1113.                     if(Signals & SIG_KILL)
  1114.                     {
  1115.                         WaitIO(TimeRequest);
  1116.  
  1117.                         CloseDevice(TimeRequest);
  1118.  
  1119.                         DeleteIORequest(TimeRequest);
  1120.  
  1121.                         DeleteMsgPort(TimePort);
  1122.  
  1123.                         Forbid();
  1124.  
  1125.                         Signal(ThisProcess,SIG_HANDSHAKE);
  1126.  
  1127.                         RemTask(CycleTask = NULL);
  1128.                     }
  1129.  
  1130.                     if(Signals & SIG_TIMER)
  1131.                     {
  1132.                         WaitIO(TimeRequest);
  1133.  
  1134.                         if(DoCycle && !HoldIt)
  1135.                             CycleColours(Forward);
  1136.                     }
  1137.                 }
  1138.             }
  1139.  
  1140.             DeleteIORequest(TimeRequest);
  1141.         }
  1142.  
  1143.         DeleteMsgPort(TimePort);
  1144.     }
  1145.  
  1146.     Forbid();
  1147.  
  1148.     CycleTask = NULL;
  1149.  
  1150.     Signal(ThisProcess,SIG_HANDSHAKE);
  1151. }
  1152.  
  1153.     /* CloseWindowSafely(struct Window *Window):
  1154.      *
  1155.      *    Close a window freeing all messages pending at
  1156.      *    its user port (taken from example source code
  1157.      *    published once upon a time in Amiga Mail).
  1158.      */
  1159.  
  1160. VOID
  1161. CloseWindowSafely(struct Window *Window)
  1162. {
  1163.     struct IntuiMessage    *IntuiMessage;
  1164.     struct Node        *Successor;
  1165.  
  1166.     Forbid();
  1167.  
  1168.     IntuiMessage = (struct IntuiMessage *)Window -> UserPort -> mp_MsgList . lh_Head;
  1169.  
  1170.     while(Successor = IntuiMessage -> ExecMessage . mn_Node . ln_Succ)
  1171.     {
  1172.         if(IntuiMessage -> IDCMPWindow == Window)
  1173.         {
  1174.             Remove(IntuiMessage);
  1175.  
  1176.             ReplyMsg((struct Message *)IntuiMessage);
  1177.         }
  1178.  
  1179.         IntuiMessage = (struct IntuiMessage *)Successor;
  1180.     }
  1181.  
  1182.     Window -> UserPort = NULL;
  1183.  
  1184.     ModifyIDCMP(Window,NULL);
  1185.  
  1186.     Permit();
  1187.  
  1188.     CloseWindow(Window);
  1189. }
  1190.  
  1191.     /* GfxCleanup():
  1192.      *
  1193.      *    Frees the graphics resources allocated by the
  1194.      *    program.
  1195.      */
  1196.  
  1197. VOID
  1198. GfxCleanup()
  1199. {
  1200.     DoCycle = FALSE;
  1201.  
  1202.     Delay(5);
  1203.  
  1204.     if(Screen)
  1205.         ScreenToBack(Screen);
  1206.  
  1207.     if(Window)
  1208.     {
  1209.         ClearMenuStrip(Window);
  1210.  
  1211.         CloseWindow(Window);
  1212.  
  1213.         Window = NULL;
  1214.     }
  1215.  
  1216.     if(Menu)
  1217.     {
  1218.         FreeMenus(Menu);
  1219.  
  1220.         Menu = NULL;
  1221.     }
  1222.  
  1223.     if(VisualInfo)
  1224.     {
  1225.         FreeVisualInfo(VisualInfo);
  1226.  
  1227.         VisualInfo = NULL;
  1228.     }
  1229.  
  1230.     if(Screen)
  1231.     {
  1232.         CloseScreen(Screen);
  1233.  
  1234.         Screen = NULL;
  1235.     }
  1236.  
  1237.     if(Palette)
  1238.     {
  1239.         FreePalette(Palette);
  1240.  
  1241.         Palette = NULL;
  1242.     }
  1243.  
  1244.     if(Range)
  1245.     {
  1246.         FreeVec(Range);
  1247.  
  1248.         Range = NULL;
  1249.     }
  1250.  
  1251.     ThisProcess -> pr_WindowPtr = OldPtr;
  1252.  
  1253.     if(LineBitMap . Planes[0])
  1254.     {
  1255.         FreeVec(LineBitMap . Planes[0]);
  1256.  
  1257.         LineBitMap . Planes[0] = NULL;
  1258.     }
  1259. }
  1260.  
  1261.     /* GfxSetup():
  1262.      *
  1263.      *    Allocates the graphics resources the program requires.
  1264.      */
  1265.  
  1266. LONG
  1267. GfxSetup()
  1268. {
  1269.     struct Rectangle     DisplayClip;
  1270.     LONG             Differ;
  1271.     WORD             i;
  1272.     double             a,p;
  1273.     UBYTE             Wrap = (1 << Depth) - 2;
  1274.     struct ColorSpec    *ColorSpec;
  1275.  
  1276.     if(Depth > 5 && !LevelPatched)
  1277.     {
  1278.         WORD LevelMax = (1 << Depth) - 1;
  1279.  
  1280.         LevelPatched = TRUE;
  1281.  
  1282.         RedLevel    = (LevelMax * RedLevel) / 31;
  1283.         GreenLevel    = (LevelMax * GreenLevel) / 31;
  1284.         BlueLevel    = (LevelMax * BlueLevel) / 31;
  1285.     }
  1286.  
  1287.     if(Depth <= 5)
  1288.         MaxRange = 16;
  1289.  
  1290.     if(!(Palette = AllocPalette(1 << Depth,Depth == 8)))
  1291.         return(FALSE);
  1292.  
  1293.     if(!(Range = (UBYTE *)AllocVec(1 << Depth,MEMF_ANY)))
  1294.         return(FALSE);
  1295.  
  1296.     a = PI / (double)((1 << Depth) - 2);
  1297.  
  1298.         /* Build a range of colour intensities mapped to the
  1299.          * sine wave amplitude.
  1300.          */
  1301.  
  1302.     for(p = 0.0, i = 0 ; (p < PI) && (i < (1 << Depth) - 2) ; p += a, i++)
  1303.         Range[i] = (UBYTE)(sin(p) * (double)(MaxRange - 1) - 0.3);
  1304.  
  1305.     if(Depth == 8)
  1306.     {
  1307.         SetPaletteTriplet(Palette,0x00,0x00,0x00,0);
  1308.         SetPaletteTriplet(Palette,0xFF,0xFF,0xFF,1);
  1309.     }
  1310.     else
  1311.     {
  1312.         SetPaletteTriplet(Palette,0x0,0x0,0x0,0);
  1313.         SetPaletteTriplet(Palette,0xF,0xF,0xF,1);
  1314.     }
  1315.  
  1316.         /* Combine all three colour ranges into a single palette. */
  1317.  
  1318.     for(i = 0 ; i < Wrap ; i++)
  1319.         SetPaletteTriplet(Palette,Range[(RedLevel + i) % Wrap],Range[(GreenLevel + i) % Wrap],Range[(BlueLevel + i) % Wrap],2 + i);
  1320.  
  1321.         /* Create the colour transition table. */
  1322.  
  1323.     for(i = 0 ; i < 16384 ; i++)
  1324.         Wave[i] = 2 + (i % ((1 << Depth) - 2));
  1325.  
  1326.         /* Create the main screen, first query how wide the
  1327.          * current overscan settings allow a screen to be.
  1328.          */
  1329.  
  1330.     if(!QueryOverscan(Mode,&DisplayClip,OSCAN_VIDEO))
  1331.         return(RETURN_FAIL + 12);
  1332.  
  1333.         /* Open a centered screen. */
  1334.  
  1335.     Differ = ((DisplayClip . MaxX - DisplayClip . MinX + 1) - Square) / 2;
  1336.  
  1337.     DisplayClip . MinX += Differ;
  1338.     DisplayClip . MaxX -= Differ;
  1339.  
  1340.         /* Allocate a couple of colour specification structures. */
  1341.  
  1342.     if(!(ColorSpec = (struct ColorSpec *)AllocVec(sizeof(struct ColorSpec) * ((1 << Depth) + 1),MEMF_ANY | MEMF_CLEAR)))
  1343.     {
  1344.             /* Open a screen with monochrome system imagery. */
  1345.  
  1346.         if(!(Screen = OpenScreenTags(NULL,
  1347.             SA_Width,    Square,
  1348.             SA_Height,    Square,
  1349.             SA_DClip,    &DisplayClip,
  1350.             SA_Left,    DisplayClip . MinX,
  1351.             SA_Depth,    Depth,
  1352.             SA_DisplayID,    Mode,
  1353.             SA_Font,    &DefaultFont,
  1354.             SA_ShowTitle,    FALSE,
  1355.             SA_Quiet,    TRUE,
  1356.             SA_AutoScroll,    TRUE,
  1357.             SA_Behind,    TRUE,
  1358.         TAG_END)))
  1359.             return(RETURN_FAIL + 13);
  1360.     }
  1361.     else
  1362.     {
  1363.             /* Set up the colour specifications to open
  1364.              * an entirely black screen.
  1365.              */
  1366.  
  1367.         for(i = 0 ; i < (1 << Depth) ; i++)
  1368.             ColorSpec[i] . ColorIndex = i;
  1369.  
  1370.         ColorSpec[i] . ColorIndex = -1;
  1371.  
  1372.             /* Open a screen with monochrome system imagery. */
  1373.  
  1374.         if(!(Screen = OpenScreenTags(NULL,
  1375.             SA_Width,    Square,
  1376.             SA_Height,    Square,
  1377.             SA_DClip,    &DisplayClip,
  1378.             SA_Left,    DisplayClip . MinX,
  1379.             SA_Depth,    Depth,
  1380.             SA_DisplayID,    Mode,
  1381.             SA_Font,    &DefaultFont,
  1382.             SA_ShowTitle,    FALSE,
  1383.             SA_Quiet,    TRUE,
  1384.             SA_AutoScroll,    TRUE,
  1385.             SA_Behind,    TRUE,
  1386.             SA_Colors,    ColorSpec,
  1387.         TAG_END)))
  1388.         {
  1389.             FreeVec(ColorSpec);
  1390.  
  1391.             return(RETURN_FAIL + 13);
  1392.         }
  1393.         else
  1394.             FreeVec(ColorSpec);
  1395.     }
  1396.  
  1397.         /* Set up the remaining data. */
  1398.  
  1399.     if(!(VisualInfo = GetVisualInfo(Screen,TAG_DONE)))
  1400.         return(RETURN_FAIL + 14);
  1401.  
  1402.     if(!(Menu = CreateMenus(MandelbrotMenu,
  1403.         GTMN_FrontPen, 0,
  1404.     TAG_DONE)))
  1405.         return(RETURN_FAIL + 15);
  1406.  
  1407.     if(!LayoutMenus(Menu,    VisualInfo,
  1408.         GTMN_TextAttr,    &DefaultFont,
  1409.     TAG_DONE))
  1410.         return(RETURN_FAIL + 16);
  1411.  
  1412.     if(!(Window = OpenWindowTags(NULL,
  1413.         WA_Width,    Screen -> Width,
  1414.         WA_Height,    Screen -> Height,
  1415.         WA_Borderless,    TRUE,
  1416.         WA_Backdrop,    TRUE,
  1417.         WA_IDCMP,    IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK | IDCMP_RAWKEY | IDCMP_VANILLAKEY | IDCMP_MENUVERIFY,
  1418.         WA_RMBTrap,    TRUE,
  1419.         WA_CustomScreen,Screen,
  1420.     TAG_END)))
  1421.         return(RETURN_FAIL + 17);
  1422.  
  1423.         /* Create a bitmap which is exactly as wide as the
  1424.          * main screen, but only a single line high.
  1425.          */
  1426.  
  1427.     InitBitMap(&LineBitMap,Depth,Square,1);
  1428.  
  1429.         /* Allocate space for the bitmap, note that the
  1430.          * bitplanes are to reside in fast ram.
  1431.          */
  1432.  
  1433.     if(LineBitMap . Planes[0] = AllocVec(LineBitMap . BytesPerRow * LineBitMap . Depth,MEMF_FAST | MEMF_CLEAR))
  1434.     {
  1435.         for(i = 1 ; i < LineBitMap . Depth ; i++)
  1436.             LineBitMap . Planes[i] = &LineBitMap . Planes[i - 1][LineBitMap . BytesPerRow];
  1437.     }
  1438.  
  1439.     SetMenuStrip(Window,Menu);
  1440.  
  1441.     OffMenu(Window,FULLMENUNUM(0,9,NOSUB));
  1442.  
  1443.     if(!UseDouble)
  1444.     {
  1445.         OffMenu(Window,FULLMENUNUM(0, 6,NOSUB));
  1446.         OffMenu(Window,FULLMENUNUM(0, 8,NOSUB));
  1447.         OffMenu(Window,FULLMENUNUM(0, 9,NOSUB));
  1448.         OffMenu(Window,FULLMENUNUM(0,10,NOSUB));
  1449.         OffMenu(Window,FULLMENUNUM(0,11,NOSUB));
  1450.         OffMenu(Window,FULLMENUNUM(0,12,NOSUB));
  1451.     }
  1452.  
  1453.     RPort = &Screen -> RastPort;
  1454.     VPort = &Screen -> ViewPort;
  1455.  
  1456.     SetRast(RPort,0);
  1457.  
  1458.     Window -> Flags &= ~WFLG_RMBTRAP;
  1459.  
  1460.     ThisProcess -> pr_WindowPtr = (APTR)Window;
  1461.  
  1462.     return(0);
  1463. }
  1464.  
  1465.     /* CloseAll(LONG ReturnCode):
  1466.      *
  1467.      *    Close all remaining resources and terminate the program.
  1468.      */
  1469.  
  1470. VOID __regargs
  1471. CloseAll(LONG ReturnCode)
  1472. {
  1473.     SetTaskPri(ThisProcess,OldPri);
  1474.  
  1475.     StopAnim();
  1476.  
  1477.     if(CycleTask)
  1478.     {
  1479.         DoCycle = FALSE;
  1480.  
  1481.         Signal(CycleTask,SIG_KILL);
  1482.  
  1483.         Wait(SIG_HANDSHAKE);
  1484.     }
  1485.  
  1486.     if(GlobalBitMap)
  1487.         FreeCustomBitMap(GlobalBitMap,TRUE);
  1488.  
  1489.     if(GlobalPalette)
  1490.         FreePalette(GlobalPalette);
  1491.  
  1492.     if(Wave)
  1493.         FreeVec(Wave);
  1494.  
  1495.     GfxCleanup();
  1496.  
  1497.     if(BackupBitMap)
  1498.         FreeCustomBitMap(BackupBitMap,FALSE);
  1499.  
  1500.     if(TimeRequest)
  1501.     {
  1502.         if(TimeRequest -> tr_node . io_Device)
  1503.             CloseDevice(TimeRequest);
  1504.  
  1505.         DeleteIORequest(TimeRequest);
  1506.     }
  1507.  
  1508.     if(TimePort)
  1509.         DeleteMsgPort(TimePort);
  1510.  
  1511.     if(IconBase)
  1512.         CloseLibrary(IconBase);
  1513.  
  1514.     if(AslBase)
  1515.         CloseLibrary(AslBase);
  1516.  
  1517.     if(IFFParseBase)
  1518.         CloseLibrary(IFFParseBase);
  1519.  
  1520.     if(GadToolsBase)
  1521.         CloseLibrary(GadToolsBase);
  1522.  
  1523.     if(GfxBase)
  1524.         CloseLibrary(GfxBase);
  1525.  
  1526.     if(IntuitionBase)
  1527.         CloseLibrary(IntuitionBase);
  1528.  
  1529.     exit(ReturnCode);
  1530. }
  1531.  
  1532.     /* OpenAll():
  1533.      *
  1534.      *    Open libraries and other data which does not
  1535.      *    require changing when the display modes are
  1536.      *    altered.
  1537.      */
  1538.  
  1539. VOID
  1540. OpenAll()
  1541. {
  1542.     ThisProcess = (struct Process *)FindTask(NULL);
  1543.  
  1544.     OldPri = SetTaskPri(ThisProcess,0);
  1545.  
  1546.     OldPtr = ThisProcess -> pr_WindowPtr;
  1547.  
  1548. #ifdef _M68040
  1549.     {
  1550.         APTR Base;
  1551.  
  1552.         if(!(Base = OpenLibrary("68040.library",0)))
  1553.             CloseAll(RETURN_FAIL + 0);
  1554.         else
  1555.             CloseLibrary(Base);
  1556.     }
  1557. #endif    /* _M68040 */
  1558.  
  1559.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)))
  1560.         CloseAll(RETURN_FAIL + 0);
  1561.  
  1562.     if(IntuitionBase -> LibNode . lib_Version >= 39)
  1563.         Is39 = TRUE;
  1564.     else
  1565.         Is39 = FALSE;
  1566.  
  1567.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)))
  1568.         CloseAll(RETURN_FAIL + 1);
  1569.  
  1570.     if(!(GadToolsBase = OpenLibrary("gadtools.library",37)))
  1571.         CloseAll(RETURN_FAIL + 2);
  1572.  
  1573.     if(!(IFFParseBase = OpenLibrary("iffparse.library",38)))
  1574.         CloseAll(RETURN_FAIL + 3);
  1575.  
  1576.     if(!(AslBase = OpenLibrary("asl.library",38)))
  1577.         CloseAll(RETURN_FAIL + 4);
  1578.  
  1579.     if(!(TimePort = (struct MsgPort *)CreateMsgPort()))
  1580.         CloseAll(RETURN_FAIL + 5);
  1581.  
  1582.     if(!(TimeRequest = (struct timerequest *)CreateIORequest(TimePort,sizeof(struct timerequest))))
  1583.         CloseAll(RETURN_FAIL + 6);
  1584.  
  1585.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
  1586.         CloseAll(RETURN_FAIL + 7);
  1587.  
  1588.     if(!(BackupBitMap = AllocCustomBitMap(8,25 * 8,8,FALSE)))
  1589.         CloseAll(RETURN_FAIL + 8);
  1590.  
  1591.     if(!(Wave = (BYTE *)AllocVec(16384,MEMF_ANY | MEMF_CLEAR)))
  1592.         CloseAll(RETURN_FAIL + 9);
  1593.  
  1594.     if(!(IconBase = OpenLibrary("icon.library",37)))
  1595.         CloseAll(RETURN_FAIL + 10);
  1596.  
  1597.     TimerBase = &TimeRequest -> tr_node . io_Device -> dd_Library;
  1598.  
  1599.     if(!(CycleTask = CreateTask("Mandel² cycling",10,CycleServer,4096)))
  1600.         CloseAll(RETURN_FAIL + 11);
  1601.     else
  1602.     {
  1603.         Wait(SIG_HANDSHAKE);
  1604.  
  1605.         if(!CycleTask)
  1606.             CloseAll(RETURN_FAIL + 11);
  1607.     }
  1608. }
  1609.  
  1610.     /* CopyLine(struct BitMap *BitMap,WORD Line):
  1611.      *
  1612.      *    Copies the contents of the single line bitmap to a given
  1613.      *    line on screen.
  1614.      */
  1615.  
  1616. VOID __regargs
  1617. CopyLine(struct BitMap *BitMap,WORD Line)
  1618. {
  1619.     WORD i;
  1620.  
  1621.     Line *= BitMap -> BytesPerRow;
  1622.  
  1623.     for(i = 0 ; i < BitMap -> Depth ; i++)
  1624.         CopyMemQuick(BitMap -> Planes[i],&RPort -> BitMap -> Planes[i][Line],BitMap -> BytesPerRow);
  1625. }
  1626.  
  1627.     /* GetTime():
  1628.      *
  1629.      *    Asks the timer.device for the current system time.
  1630.      */
  1631.  
  1632. VOID
  1633. GetTime()
  1634. {
  1635.     TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  1636.  
  1637.     DoIO(TimeRequest);
  1638. }
  1639.  
  1640.     /* BlockWindow():
  1641.      *
  1642.      *    Blocks the menu bar of the window and sets the busy
  1643.      *    mouse pointer.
  1644.      */
  1645.  
  1646. VOID
  1647. BlockWindow()
  1648. {
  1649.     HoldIt = TRUE;
  1650.  
  1651.     SetWait(Window);
  1652.  
  1653.     Window -> Flags |= WFLG_RMBTRAP;
  1654. }
  1655.  
  1656.     /* ReleaseWindow():
  1657.      *
  1658.      *    Reenables the menu bar of the window and resets the
  1659.      *    mouse pointer to the default mouse pointer.
  1660.      */
  1661.  
  1662. VOID
  1663. ReleaseWindow()
  1664. {
  1665.     ClrWait(Window);
  1666.  
  1667.     Window -> Flags &= ~WFLG_RMBTRAP;
  1668.  
  1669.     HoldIt = FALSE;
  1670. }
  1671.  
  1672.     /* GetFile():
  1673.      *
  1674.      *    Get a file name using the asl.library file requester.
  1675.      */
  1676.  
  1677. BYTE
  1678. GetFile(UBYTE *Title,UBYTE *Directory,UBYTE *Name,UBYTE *Buffer,UBYTE *Pattern,BYTE SaveFlag)
  1679. {
  1680.     struct FileRequester    *AslFileRequest;
  1681.     BYTE             Result = FALSE;
  1682.     LONG             Flags;
  1683.  
  1684.     if(!Directory[0])
  1685.         NameFromLock(ThisProcess -> pr_CurrentDir,Directory,256);
  1686.  
  1687.     if(Pattern)
  1688.     {
  1689.         Flags = FILF_PATGAD;
  1690.  
  1691.         if(!Pattern[0])
  1692.             Pattern = "~(#?.info)";
  1693.     }
  1694.     else
  1695.     {
  1696.         Flags = 0;
  1697.  
  1698.         Pattern = "~(#?.info)";
  1699.     }
  1700.  
  1701.     if(SaveFlag)
  1702.         Flags |= FILF_SAVE;
  1703.  
  1704.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  1705.         ASL_Window,    Window,
  1706.         ASL_File,    Name,
  1707.         ASL_Dir,    Directory,
  1708.         ASL_Hail,    Title,
  1709.         ASL_FuncFlags,    Flags,
  1710.         ASL_Pattern,    Pattern,
  1711.         ASL_OKText,    SaveFlag ? "Save" : "Open",
  1712.     TAG_DONE))
  1713.     {
  1714.         if(RequestFile(AslFileRequest))
  1715.         {
  1716.             if(AslFileRequest -> rf_File[0])
  1717.             {
  1718.                 strcpy(Buffer,AslFileRequest -> rf_Dir);
  1719.  
  1720.                 AddPart((UBYTE *)Buffer,(UBYTE *)AslFileRequest -> rf_File,256);
  1721.  
  1722.                 Result = TRUE;
  1723.             }
  1724.         }
  1725.     }
  1726.  
  1727.     FreeFileRequest(AslFileRequest);
  1728.  
  1729.     return(Result);
  1730. }
  1731.  
  1732.     /* MyEasyRequest():
  1733.      *
  1734.      *    EasyRequestArgs stub routine.
  1735.      */
  1736.  
  1737. WORD __stdargs
  1738. MyEasyRequest(UBYTE *Gadgets,UBYTE *Text,...)
  1739. {
  1740.     struct EasyStruct    Easy;
  1741.     WORD            Result;
  1742.     ULONG            IDCMP = NULL;
  1743.     va_list             VarArgs;
  1744.  
  1745.     Easy . es_StructSize    = sizeof(struct EasyStruct);
  1746.     Easy . es_Flags        = NULL;
  1747.     Easy . es_Title        = (UBYTE *)"Mandel²";
  1748.     Easy . es_TextFormat    = (UBYTE *)Text;
  1749.     Easy . es_GadgetFormat    = (UBYTE *)Gadgets;
  1750.  
  1751.     va_start(VarArgs,Text);
  1752.     Result = EasyRequestArgs(Window,&Easy,&IDCMP,VarArgs);
  1753.     va_end(VarArgs);
  1754.  
  1755.     return(Result);
  1756. }
  1757.  
  1758.     /* Random(LONG MaxValue)
  1759.      *
  1760.      *    Small random number generator.
  1761.      */
  1762.  
  1763. ULONG __regargs
  1764. Random(LONG MaxValue)
  1765. {
  1766.     STATIC ULONG RandomSeed = 213567657;
  1767.  
  1768.     RandomSeed = RandomSeed * custom . vhposr + 8754331;
  1769.  
  1770.     return(RandomSeed % MaxValue);
  1771. }
  1772.  
  1773.     /* CreateAllCoordsGadgets():
  1774.      *
  1775.      *    Creates all gadgets required by the coordinates control panel.
  1776.      */
  1777.  
  1778. struct Gadget *
  1779. CreateAllCoordsGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
  1780. {
  1781.     struct Gadget        *Gadget;
  1782.     struct NewGadget     NewGadget;
  1783.     UWORD             Counter = 0;
  1784.     UBYTE             Buffer[40];
  1785.  
  1786.     if(Gadget = CreateContext(GadgetList))
  1787.     {
  1788.         NewGadget . ng_Width        = COORDS_WIDTH - 20;
  1789.         NewGadget . ng_Height        = 14;
  1790.         NewGadget . ng_GadgetText    = "Real part (x-coordinate)";
  1791.         NewGadget . ng_TextAttr        = &DefaultFont;
  1792.         NewGadget . ng_VisualInfo    = VisualInfo;
  1793.         NewGadget . ng_GadgetID        = Counter;
  1794.         NewGadget . ng_Flags        = PLACETEXT_ABOVE;
  1795.         NewGadget . ng_LeftEdge        = 10;
  1796.         NewGadget . ng_TopEdge        = 2 + TopEdge + 14;
  1797.  
  1798.         sprintf(Buffer,"%g",MinReal);
  1799.  
  1800.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  1801.             GTST_MaxChars,        40,
  1802.             GTST_String,        Buffer,
  1803.             STRINGA_Justification,    STRINGCENTER,
  1804.         TAG_DONE);
  1805.  
  1806.         NewGadget . ng_GadgetText    = "Imaginary part (y-coordinate)";
  1807.         NewGadget . ng_GadgetID        = Counter;
  1808.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 16;
  1809.  
  1810.         sprintf(Buffer,"%g",MinImaginary);
  1811.  
  1812.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  1813.             GTST_MaxChars,        40,
  1814.             GTST_String,        Buffer,
  1815.             STRINGA_Justification,    STRINGCENTER,
  1816.         TAG_DONE);
  1817.  
  1818.         NewGadget . ng_GadgetText    = "Size";
  1819.         NewGadget . ng_GadgetID        = Counter;
  1820.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 16;
  1821.  
  1822.         sprintf(Buffer,"%g",RealWidth);
  1823.  
  1824.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  1825.             GTST_MaxChars,        40,
  1826.             GTST_String,        Buffer,
  1827.             STRINGA_Justification,    STRINGCENTER,
  1828.         TAG_DONE);
  1829.  
  1830.         NewGadget . ng_Width        = 68;
  1831.         NewGadget . ng_Height        = 12;
  1832.         NewGadget . ng_GadgetText    = "Accept";
  1833.         NewGadget . ng_GadgetID        = Counter;
  1834.         NewGadget . ng_Flags        = 0;
  1835.         NewGadget . ng_TopEdge        = COORDS_HEIGHT - 3 - NewGadget . ng_Height;
  1836.  
  1837.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  1838.             TAG_DONE);
  1839.  
  1840.         NewGadget . ng_GadgetText    = "Cancel";
  1841.         NewGadget . ng_GadgetID        = Counter;
  1842.         NewGadget . ng_LeftEdge        = COORDS_WIDTH - 10 - NewGadget . ng_Width;
  1843.  
  1844.         GadgetArray[Counter] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  1845.             TAG_DONE);
  1846.     }
  1847.  
  1848.     return(Gadget);
  1849. }
  1850.  
  1851. STATIC STRPTR __saveds
  1852. ShowOffset(struct Gadget *SomeGadget,WORD Level)
  1853. {
  1854.     STATIC UBYTE LevelBuffer[10];
  1855.  
  1856.     UWORD Mid = ((1 << Depth) - 3) / 2;
  1857.  
  1858.     if(Level == Mid)
  1859.         strcpy(LevelBuffer,"(   0)");
  1860.     else
  1861.     {
  1862.         if(Level < Mid)
  1863.             sprintf(LevelBuffer,"(-%3d)",Mid - Level);
  1864.         else
  1865.             sprintf(LevelBuffer,"(+%3d)",Level - Mid);
  1866.     }
  1867.  
  1868.     return(LevelBuffer);
  1869. }
  1870.  
  1871.  
  1872.     /* CreateAllPaletteGadgets():
  1873.      *
  1874.      *    Creates all gadgets required by the palette control panel.
  1875.      */
  1876.  
  1877. struct Gadget *
  1878. CreateAllPaletteGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
  1879. {
  1880.     struct Gadget        *Gadget;
  1881.     struct NewGadget     NewGadget;
  1882.     UWORD             Counter = 0;
  1883.  
  1884.     if(Gadget = CreateContext(GadgetList))
  1885.     {
  1886.         NewGadget . ng_Width        = 134;
  1887.         NewGadget . ng_Height        = 12;
  1888.         NewGadget . ng_GadgetText    = "Red        ";
  1889.         NewGadget . ng_TextAttr        = &DefaultFont;
  1890.         NewGadget . ng_VisualInfo    = VisualInfo;
  1891.         NewGadget . ng_GadgetID        = Counter;
  1892.         NewGadget . ng_Flags        = PLACETEXT_LEFT;
  1893.         NewGadget . ng_LeftEdge        = 18 + 8 * strlen(NewGadget . ng_GadgetText);
  1894.         NewGadget . ng_TopEdge        = 1 + TopEdge;
  1895.  
  1896.         GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
  1897.             GTSL_Min,        0,
  1898.             GTSL_Max,        (1 << Depth) - 3,
  1899.             GTSL_Level,        RedLevel,
  1900.             GTSL_DispFunc,        ShowOffset,
  1901.             GTSL_LevelFormat,    "%s",
  1902.             GTSL_MaxLevelLen,    6,
  1903.         TAG_DONE);
  1904.  
  1905.         NewGadget . ng_GadgetText    = "Green      ";
  1906.         NewGadget . ng_GadgetID        = Counter;
  1907.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  1908.  
  1909.         GadgetArray[Counter++] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
  1910.             GTSL_Min,        0,
  1911.             GTSL_Max,        (1 << Depth) - 3,
  1912.             GTSL_Level,        GreenLevel,
  1913.             GTSL_DispFunc,        ShowOffset,
  1914.             GTSL_LevelFormat,    "%s",
  1915.             GTSL_MaxLevelLen,    6,
  1916.         TAG_DONE);
  1917.  
  1918.         NewGadget . ng_GadgetText    = "Blue       ";
  1919.         NewGadget . ng_GadgetID        = Counter;
  1920.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 1;
  1921.  
  1922.         GadgetArray[Counter] = Gadget = CreateGadget(SLIDER_KIND,Gadget,&NewGadget,
  1923.             GTSL_Min,        0,
  1924.             GTSL_Max,        (1 << Depth) - 3,
  1925.             GTSL_Level,        BlueLevel,
  1926.             GTSL_DispFunc,        ShowOffset,
  1927.             GTSL_LevelFormat,    "%s",
  1928.             GTSL_MaxLevelLen,    6,
  1929.         TAG_DONE);
  1930.     }
  1931.  
  1932.     return(Gadget);
  1933. }
  1934.  
  1935.     /* CreateAllScrollGadgets():
  1936.      *
  1937.      *    Creates all the gadgets required by the scroll amount
  1938.      *    control panel.
  1939.      */
  1940.  
  1941. struct Gadget *
  1942. CreateAllScrollGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
  1943. {
  1944.     struct Gadget        *Gadget;
  1945.     struct NewGadget     NewGadget;
  1946.     UWORD             Counter = 0;
  1947.  
  1948.     if(Gadget = CreateContext(GadgetList))
  1949.     {
  1950.         NewGadget . ng_Width        = 44;
  1951.         NewGadget . ng_Height        = 14;
  1952.         NewGadget . ng_GadgetText    = "Scroll amount";
  1953.         NewGadget . ng_TextAttr        = &DefaultFont;
  1954.         NewGadget . ng_VisualInfo    = VisualInfo;
  1955.         NewGadget . ng_GadgetID        = Counter;
  1956.         NewGadget . ng_Flags        = 0;
  1957.         NewGadget . ng_LeftEdge        = (strlen(NewGadget . ng_GadgetText) + 2) * 8 + 1;
  1958.         NewGadget . ng_TopEdge        = 1 + TopEdge;
  1959.  
  1960.         GadgetArray[Counter++] = Gadget = CreateGadget(INTEGER_KIND,Gadget,&NewGadget,
  1961.             GTIN_MaxChars,    3,
  1962.             GTIN_Number,    (LONG)MaxScroll,
  1963.         TAG_DONE);
  1964.  
  1965.         NewGadget . ng_Width        = 52;
  1966.         NewGadget . ng_Height        = 12;
  1967.         NewGadget . ng_GadgetText    = "Accept";
  1968.         NewGadget . ng_GadgetID        = Counter;
  1969.         NewGadget . ng_Flags        = 0;
  1970.         NewGadget . ng_LeftEdge        = 10;
  1971.         NewGadget . ng_TopEdge        = SCROLL_HEIGHT - 3 - NewGadget . ng_Height;
  1972.  
  1973.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  1974.             TAG_DONE);
  1975.  
  1976.         NewGadget . ng_GadgetText    = "Cancel";
  1977.         NewGadget . ng_GadgetID        = Counter;
  1978.         NewGadget . ng_LeftEdge        = SCROLL_WIDTH - 10 - NewGadget . ng_Width;
  1979.  
  1980.         GadgetArray[Counter] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  1981.             TAG_DONE);
  1982.     }
  1983.  
  1984.     return(Gadget);
  1985. }
  1986.  
  1987.     /* InfoText():
  1988.      *
  1989.      *    Renders a small position and size information text into
  1990.      *    the left bottom corner of the screen.
  1991.      */
  1992.  
  1993. VOID
  1994. InfoText()
  1995. {
  1996.     struct TextFont    *OldFont;
  1997.     UBYTE         Buffer[80];
  1998.     WORD         i;
  1999.     struct RastPort    *RPort = Window -> RPort;
  2000.  
  2001.     BlockWindow();
  2002.  
  2003.     OldFont = RPort -> Font;
  2004.  
  2005.     SetFont(RPort,&DigitFont);
  2006.     SetAPen(RPort,CurrentPen = 1);
  2007.  
  2008.     sprintf(Buffer,"(/%1.04e )/%1.04e %1.04e*%1.04e",MinReal,MinImaginary,RealWidth,ImaginaryHeight);
  2009.  
  2010.     for(i = 0 ; i < strlen(Buffer) ; i++)
  2011.     {
  2012.         if(Buffer[i] == 'e')
  2013.             Buffer[i] = '$';
  2014.     }
  2015.  
  2016.     SetDrMd(RPort,JAM1);
  2017.  
  2018.     Move(RPort,1,Window -> Height - 2);
  2019.     Text(RPort,Buffer,strlen(Buffer));
  2020.  
  2021.     SetFont(RPort,OldFont);
  2022.     SetDrMd(RPort,JAM2);
  2023. }
  2024.  
  2025.     /* CalculateFrames():
  2026.      *
  2027.      *    Precalculates the number of pictures to be generated
  2028.      *    when zooming to a specific location in the Mandelbrot
  2029.      *    set.
  2030.      */
  2031.  
  2032. WORD
  2033. CalculateFrames(double MinReal,double MinImaginary,double Size)
  2034. {
  2035.     double    Data[3],
  2036.         Div,
  2037.         Value,
  2038.         FourPixels,
  2039.         GlobalSize,
  2040.         GlobalMinReal,
  2041.         GlobalMinImaginary;
  2042.     BYTE    Render,
  2043.         i;
  2044.     WORD    Count = 0;
  2045.  
  2046.     GlobalSize        = LastSize;
  2047.     GlobalMinReal        = LastMinReal;
  2048.     GlobalMinImaginary    = LastMinImaginary;
  2049.  
  2050.     do
  2051.     {
  2052.         Data[0]    = GlobalSize - Size;
  2053.         Data[1]    = MinReal - GlobalMinReal;
  2054.         Data[2] = MinImaginary - GlobalMinImaginary;
  2055.  
  2056.         Value    = fabs(Data[0]);
  2057.         Render    = FALSE;
  2058.  
  2059.         for(i = 0 ; i < 3 ; i++)
  2060.         {
  2061.             if(Data[i] != 0.0)
  2062.                 Render = TRUE;
  2063.  
  2064.             if(fabs(Data[i]) > Value)
  2065.                 Value = fabs(Data[i]);
  2066.         }
  2067.  
  2068.         if(Render)
  2069.         {
  2070.             FourPixels    = MaxScroll * (GlobalSize / (double)Screen -> Width);
  2071.             Div        = Value;
  2072.  
  2073.             if(Value > FourPixels)
  2074.                 Value = FourPixels;
  2075.  
  2076.             Div /= Value;
  2077.  
  2078.             GlobalSize        -= Data[0] / Div;
  2079.             GlobalMinReal        += Data[1] / Div;
  2080.             GlobalMinImaginary    += Data[2] / Div;
  2081.  
  2082.             Count++;
  2083.         }
  2084.     }
  2085.     while(Render);
  2086.  
  2087.     return(Count);
  2088. }
  2089.  
  2090.     /* CheckAbort():
  2091.      *
  2092.      *    Provides a safe callback routine to allow the anim
  2093.      *    player to check for a user abort.
  2094.      */
  2095.  
  2096. BYTE
  2097. CheckAbort()
  2098. {
  2099.     if(CheckSignal(SIG_WINDOW))
  2100.     {
  2101.         struct IntuiMessage    *Massage;
  2102.         ULONG             Class,Code;
  2103.  
  2104.         while(Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
  2105.         {
  2106.             Class    = Massage -> Class;
  2107.             Code    = Massage -> Code;
  2108.  
  2109.             GT_ReplyIMsg(Massage);
  2110.  
  2111.             if((Class == IDCMP_MOUSEBUTTONS && !(Code & IECODE_UP_PREFIX)) || Class == IDCMP_VANILLAKEY)
  2112.                 return(TRUE);
  2113.         }
  2114.     }
  2115.     else
  2116.         return(FALSE);
  2117. }
  2118.  
  2119.     /* ReplayAnim():
  2120.      *
  2121.      *    Loads and replays an animation file.
  2122.      */
  2123.  
  2124. BYTE
  2125. ReplayAnim()
  2126. {
  2127.     BYTE     Success = FALSE;
  2128.     UBYTE    *DummyChar;
  2129.  
  2130.     strcpy(DummyBuffer,AnimPlayName);
  2131.  
  2132.     DummyChar = PathPart(DummyBuffer);
  2133.  
  2134.     *DummyChar = 0;
  2135.  
  2136.     if(GetFile("Replay animation",DummyBuffer,FilePart(AnimPlayName),DummyBuffer,"~(#?.info)",FALSE))
  2137.     {
  2138.         struct MinList *List;
  2139.  
  2140.         if(List = LoadAnim(DummyBuffer))
  2141.         {
  2142.             LONG Error = ValidateAnim(List,Screen);
  2143.  
  2144.             if(!Error)
  2145.             {
  2146.                 strcpy(AnimPlayName,DummyBuffer);
  2147.  
  2148.                 SetClear(Window);
  2149.  
  2150.                 if(!PlayAnim(List,Screen,CheckAbort))
  2151.                     MyEasyRequest("Continue","Not enough memory for\ndisplay buffer.");
  2152.                 else
  2153.                     Success = TRUE;
  2154.  
  2155.                 SetWait(Window);
  2156.             }
  2157.             else
  2158.                 MyEasyRequest("Continue","Error validating animation\n(%s)",AnimErrors[Error]);
  2159.  
  2160.             DeleteAnim(List);
  2161.         }
  2162.         else
  2163.             MyEasyRequest("Continue","Could not read animation file\n%s.",FilePart(DummyBuffer));
  2164.     }
  2165.  
  2166.     return(Success);
  2167. }
  2168.  
  2169.     /* RunAnim():
  2170.      *
  2171.      *    This routine calculates the single animation frames and
  2172.      *    stores them in the anim file.
  2173.      */
  2174.  
  2175. VOID
  2176. RunAnim()
  2177. {
  2178.     double    Data[3],
  2179.         Value,
  2180.         Div,
  2181.         SomePixels;
  2182.     BYTE    Render,
  2183.         i;
  2184.  
  2185.     LastSize        = RealWidth;
  2186.     LastMinReal        = MinReal;
  2187.     LastMinImaginary    = MinImaginary;
  2188.  
  2189.     NewCoords = FALSE;
  2190.  
  2191. /*    Coords();*/
  2192.  
  2193.     while(AnimRunning && !NewCoords)
  2194.         Zoom();
  2195.  
  2196.     if(NewCoords)
  2197.     {
  2198.         if(!AnimInfo)
  2199.         {
  2200.             UBYTE *DummyChar;
  2201.  
  2202.             AnimRunning = FALSE;
  2203.  
  2204.             strcpy(DummyBuffer,AnimSaveName);
  2205.  
  2206.             DummyChar = PathPart(DummyBuffer);
  2207.  
  2208.             *DummyChar = 0;
  2209.  
  2210.             if(GetFile("Begin animation",DummyBuffer,FilePart(AnimSaveName),DummyBuffer,"~(#?.info)",TRUE))
  2211.             {
  2212.                 if(Frame)
  2213.                 {
  2214.                     WORD    X,Y,
  2215.                         Width;
  2216.                     double    Pixel;
  2217.  
  2218.                     Pixel    = LastSize / (double)Screen -> Width;
  2219.  
  2220.                     X    = (WORD)(fabs(LastMinReal - MainMinReal) / Pixel);
  2221.                     Y    = (WORD)(fabs(LastMinImaginary - MainMinImaginary) / Pixel);
  2222.                     Width    = (WORD)(MainRealWidth / Pixel);
  2223.  
  2224.                     if(X || Y || Width != Screen -> Width)
  2225.                     {
  2226.                         SetAPen(Window -> RPort,CurrentPen = 1);
  2227.                         DrawSquare(Window -> RPort,X,Y,Width);
  2228.                     }
  2229.                 }
  2230.  
  2231.                 if(Include)
  2232.                     InfoText();
  2233.  
  2234.                 if(AnimInfo = OpenAnim(DummyBuffer,Screen))
  2235.                 {
  2236.                     if(!ThisProcess -> pr_CLI)
  2237.                         PutDiskObject(DummyBuffer,&AnimIcon);
  2238.  
  2239.                     OffMenu(Window,FULLMENUNUM(0, 0,NOSUB));
  2240.                     OffMenu(Window,FULLMENUNUM(0, 1,NOSUB));
  2241.                     OffMenu(Window,FULLMENUNUM(0, 2,NOSUB));
  2242.                     OffMenu(Window,FULLMENUNUM(0, 6,NOSUB));
  2243.                     OffMenu(Window,FULLMENUNUM(0, 8,NOSUB));
  2244.                     OnMenu (Window,FULLMENUNUM(0, 9,NOSUB));
  2245.                     OffMenu(Window,FULLMENUNUM(0,11,NOSUB));
  2246.                     OffMenu(Window,FULLMENUNUM(0,12,NOSUB));
  2247.                     OffMenu(Window,FULLMENUNUM(0,14,NOSUB));
  2248.  
  2249.                     OffMenu(Window,FULLMENUNUM(1, 0,NOSUB));
  2250.                     OffMenu(Window,FULLMENUNUM(1, 1,NOSUB));
  2251.                     OffMenu(Window,FULLMENUNUM(1, 2,NOSUB));
  2252.                     OffMenu(Window,FULLMENUNUM(1, 5,NOSUB));
  2253.                     OffMenu(Window,FULLMENUNUM(1, 7,NOSUB));
  2254.                     OffMenu(Window,FULLMENUNUM(1, 9,NOSUB));
  2255.  
  2256.                     AnimRunning = TRUE;
  2257.  
  2258.                     strcpy(AnimSaveName,DummyBuffer);
  2259.                 }
  2260.             }
  2261.         }
  2262.  
  2263.         if(AnimRunning)
  2264.         {
  2265.             RealWidth        = LastSize;
  2266.             ImaginaryHeight        = LastSize;
  2267.  
  2268.             MinReal            = LastMinReal;
  2269.             MinImaginary        = LastMinImaginary;
  2270.  
  2271.             LastSize        = MainRealWidth;
  2272.             LastMinReal        = MainMinReal;
  2273.             LastMinImaginary    = MainMinImaginary;
  2274.  
  2275.             do
  2276.             {
  2277.                 Data[0]    = RealWidth - LastSize;
  2278.                 Data[1]    = LastMinReal - MinReal;
  2279.                 Data[2] = LastMinImaginary - MinImaginary;
  2280.  
  2281.                 Value    = fabs(Data[0]);
  2282.                 Render    = FALSE;
  2283.  
  2284.                 for(i = 0 ; i < 3 ; i++)
  2285.                 {
  2286.                     if(Data[i] != 0.0)
  2287.                         Render = TRUE;
  2288.  
  2289.                     if(fabs(Data[i]) > Value)
  2290.                         Value = fabs(Data[i]);
  2291.                 }
  2292.  
  2293.                 if(Render)
  2294.                 {
  2295.                     SomePixels    = MaxScroll * (RealWidth / (double)Screen -> Width);
  2296.                     Div        = Value;
  2297.  
  2298.                     if(Value > SomePixels)
  2299.                         Value = SomePixels;
  2300.  
  2301.                     Div /= Value;
  2302.  
  2303.                     RealWidth    -= Data[0] / Div;
  2304.                     ImaginaryHeight    -= Data[0] / Div;
  2305.                     MinReal        += Data[1] / Div;
  2306.                     MinImaginary    += Data[2] / Div;
  2307.  
  2308.                     RealStep    = RealWidth / (double)Window -> Width;
  2309.                     ImaginaryStep    = ImaginaryHeight / (double)Window -> Height;
  2310.  
  2311.                     AreaActive    = FALSE;
  2312.                     Running        = TRUE;
  2313.  
  2314.                     FullPicture    = TRUE;
  2315.  
  2316.                     SetRast(Window -> RPort,0);
  2317.  
  2318.                     Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,0,0,Window -> Width >> 1,Window -> Height >> 1);
  2319.                     Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Window -> Width >> 1,0,Window -> Width >> 1,Window -> Height >> 1);
  2320.  
  2321.                     Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,0,Window -> Height >> 1,Window -> Width >> 1,Window -> Height >> 1);
  2322.                     Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Window -> Width >> 1,Window -> Height >> 1,Window -> Width >> 1,Window -> Height >> 1);
  2323.  
  2324.                     if(FullPicture)
  2325.                     {
  2326.                         BlockWindow();
  2327.  
  2328.                         if(Frame)
  2329.                         {
  2330.                             WORD    X,Y,Width;
  2331.                             double    Pixel;
  2332.  
  2333.                             Pixel    = RealWidth / (double)Screen -> Width;
  2334.  
  2335.                             X    = (WORD)(fabs(MinReal - LastMinReal) / Pixel);
  2336.                             Y    = (WORD)(fabs(MinImaginary - LastMinImaginary) / Pixel);
  2337.                             Width    = (WORD)(LastSize / Pixel);
  2338.  
  2339.                             if(X || Y || Width != Screen -> Width)
  2340.                             {
  2341.                                 SetAPen(Window -> RPort,CurrentPen = 1);
  2342.                                 DrawSquare(Window -> RPort,X,Y,Width);
  2343.                             }
  2344.                         }
  2345.  
  2346.                         if(Include)
  2347.                             InfoText();
  2348.  
  2349.                         AddAnim(AnimInfo);
  2350.  
  2351.                         ReleaseWindow();
  2352.                     }
  2353.  
  2354.                     if(!AnimRunning)
  2355.                         break;
  2356.                 }
  2357.             }
  2358.             while(Render);
  2359.  
  2360.             if(!Render)
  2361.             {
  2362.                 MoveScreen(Screen,0,-Screen -> TopEdge);
  2363.  
  2364.                 ScreenToFront(Screen);
  2365.  
  2366.                 ActivateWindow(Window);
  2367.  
  2368.                 Delay(10);
  2369.  
  2370.                 DisplayBeep(Screen);
  2371.             }
  2372.         }
  2373.  
  2374.         AreaActive    = FALSE;
  2375.         Running        = FALSE;
  2376.     }
  2377.     else
  2378.         StopAnim();
  2379. }
  2380.  
  2381.     /* StopAnim():
  2382.      *
  2383.      *    Stops the animation generation.
  2384.      */
  2385.  
  2386. VOID
  2387. StopAnim()
  2388. {
  2389.     if(AnimRunning)
  2390.     {
  2391.         AnimRunning = FALSE;
  2392.  
  2393.         OnMenu (Window,FULLMENUNUM(0, 0,NOSUB));
  2394.         OnMenu (Window,FULLMENUNUM(0, 1,NOSUB));
  2395.         OnMenu (Window,FULLMENUNUM(0, 2,NOSUB));
  2396.         OnMenu (Window,FULLMENUNUM(0,14,NOSUB));
  2397.  
  2398.         if(UseDouble)
  2399.         {
  2400.             OnMenu (Window,FULLMENUNUM(0, 6,NOSUB));
  2401.             OnMenu (Window,FULLMENUNUM(0, 8,NOSUB));
  2402.             OffMenu(Window,FULLMENUNUM(0, 9,NOSUB));
  2403.             OnMenu (Window,FULLMENUNUM(0,11,NOSUB));
  2404.             OnMenu (Window,FULLMENUNUM(0,12,NOSUB));
  2405.         }
  2406.         else
  2407.         {
  2408.             OffMenu(Window,FULLMENUNUM(0, 6,NOSUB));
  2409.             OffMenu(Window,FULLMENUNUM(0, 8,NOSUB));
  2410.             OffMenu(Window,FULLMENUNUM(0, 9,NOSUB));
  2411.             OffMenu(Window,FULLMENUNUM(0,10,NOSUB));
  2412.             OffMenu(Window,FULLMENUNUM(0,11,NOSUB));
  2413.             OffMenu(Window,FULLMENUNUM(0,12,NOSUB));
  2414.         }
  2415.  
  2416.         OnMenu (Window,FULLMENUNUM(1, 0,NOSUB));
  2417.         OnMenu (Window,FULLMENUNUM(1, 1,NOSUB));
  2418.         OnMenu (Window,FULLMENUNUM(1, 2,NOSUB));
  2419.         OnMenu (Window,FULLMENUNUM(1, 5,NOSUB));
  2420.         OnMenu (Window,FULLMENUNUM(1, 7,NOSUB));
  2421.         OnMenu (Window,FULLMENUNUM(1, 9,NOSUB));
  2422.  
  2423.         if(AnimInfo)
  2424.         {
  2425.             CloseAnim(AnimInfo,TRUE);
  2426.  
  2427.             AnimInfo = NULL;
  2428.         }
  2429.     }
  2430. }
  2431.  
  2432.     /* Coords():
  2433.      *
  2434.      *    This routine implements the coordinates control panel.
  2435.      */
  2436.  
  2437. VOID
  2438. Coords()
  2439. {
  2440.     struct Gadget    *GadgetList = NULL;
  2441.     struct Gadget    *GadgetArray[5];
  2442.     struct Window    *CoordsWindow;
  2443.  
  2444.     double         TempMinReal,
  2445.              TempMinImaginary,
  2446.              TempRealWidth,
  2447.              TempImaginaryHeight;
  2448.  
  2449.     BYTE         MadeChanges = FALSE;
  2450.  
  2451.     TempMinReal        = MinReal;
  2452.     TempMinImaginary    = MinImaginary;
  2453.     TempRealWidth        = RealWidth;
  2454.     TempImaginaryHeight    = ImaginaryHeight;
  2455.  
  2456.     if(CreateAllCoordsGadgets(&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
  2457.     {
  2458.         if(CoordsWindow = OpenWindowTags(NULL,
  2459.             WA_Width,    COORDS_WIDTH,
  2460.             WA_Height,    COORDS_HEIGHT,
  2461.             WA_Top,        (Screen -> Height - COORDS_HEIGHT) >> 1,
  2462.             WA_Left,    (Screen -> Width - COORDS_WIDTH) >> 1,
  2463.             WA_Activate,    TRUE,
  2464.             WA_CloseGadget,    TRUE,
  2465.             WA_RMBTrap,    TRUE,
  2466.             WA_DragBar,    TRUE,
  2467.             WA_IDCMP,    IDCMP_CLOSEWINDOW | BUTTONIDCMP | STRINGIDCMP,
  2468.             WA_Title,    "Coordinates",
  2469.             WA_CustomScreen,Screen,
  2470.         TAG_DONE))
  2471.         {
  2472.             struct IntuiMessage    *Massage;
  2473.             ULONG             Class;
  2474.             struct Gadget        *Gadget;
  2475.             BYTE             Terminated = FALSE;
  2476.  
  2477.             AddGList(CoordsWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  2478.             RefreshGList(GadgetList,CoordsWindow,NULL,(UWORD)-1);
  2479.             GT_RefreshWindow(CoordsWindow,NULL);
  2480.  
  2481.             ActivateGadget(GadgetArray[0],CoordsWindow,NULL);
  2482.  
  2483.             while(!Terminated)
  2484.             {
  2485.                 WaitPort(CoordsWindow -> UserPort);
  2486.  
  2487.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(CoordsWindow -> UserPort)))
  2488.                 {
  2489.                     Class    = Massage -> Class;
  2490.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  2491.  
  2492.                     GT_ReplyIMsg(Massage);
  2493.  
  2494.                     if(Class == IDCMP_CLOSEWINDOW)
  2495.                         Terminated = TRUE;
  2496.  
  2497.                     if(Class == IDCMP_GADGETUP)
  2498.                     {
  2499.                         double Value;
  2500.  
  2501.                         switch(Gadget -> GadgetID)
  2502.                         {
  2503.                             case 3:    if(MadeChanges)
  2504.                                 {
  2505.                                     MinReal        = TempMinReal;
  2506.                                     MinImaginary    = TempMinImaginary;
  2507.                                     RealWidth    = TempRealWidth;
  2508.                                     ImaginaryHeight    = TempImaginaryHeight;
  2509.  
  2510.                                     RealStep    = RealWidth / (double)Window -> Width;
  2511.                                     ImaginaryStep    = ImaginaryHeight / (double)Window -> Height;
  2512.  
  2513.                                     MainMinReal        = MinReal;
  2514.                                     MainMinImaginary    = MinImaginary;
  2515.                                     MainRealWidth        = RealWidth;
  2516.                                     MainImaginaryHeight    = ImaginaryHeight;
  2517.  
  2518.                                     NewCoords    = TRUE;
  2519.                                     Running        = FALSE;
  2520.                                     AreaActive    = FALSE;
  2521.                                 }
  2522.  
  2523.                                 Terminated = TRUE;
  2524.                                 break;
  2525.  
  2526.                             case 4:    Terminated = TRUE;
  2527.                                 break;
  2528.  
  2529.                             default:Value = atof(((struct StringInfo *)Gadget -> SpecialInfo) -> Buffer);
  2530.  
  2531.                                 MadeChanges = TRUE;
  2532.  
  2533.                                 switch(Gadget -> GadgetID)
  2534.                                 {
  2535.                                     case 0:    TempMinReal = Value;
  2536.                                         ActivateGadget(GadgetArray[1],CoordsWindow,NULL);
  2537.                                         break;
  2538.  
  2539.                                     case 1:    TempMinImaginary = Value;
  2540.                                         ActivateGadget(GadgetArray[2],CoordsWindow,NULL);
  2541.                                         break;
  2542.  
  2543.                                     case 2:    TempRealWidth        = Value;
  2544.                                         TempImaginaryHeight    = Value;
  2545.  
  2546.                                         ActivateGadget(GadgetArray[0],CoordsWindow,NULL);
  2547.                                         break;
  2548.                                 }
  2549.  
  2550.                                 break;
  2551.                         }
  2552.                     }
  2553.                 }
  2554.             }
  2555.  
  2556.             CloseWindow(CoordsWindow);
  2557.         }
  2558.     }
  2559.  
  2560.     FreeGadgets(GadgetList);
  2561. }
  2562.  
  2563.     /* AdjustPalette():
  2564.      *
  2565.      *    This routine implements the palette control panel.
  2566.      */
  2567.  
  2568. VOID
  2569. AdjustPalette()
  2570. {
  2571.     struct Gadget    *GadgetList = NULL;
  2572.     struct Gadget    *GadgetArray[3];
  2573.     struct Window    *Window;
  2574.  
  2575.     if(CreateAllPaletteGadgets(&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
  2576.     {
  2577.         if(Window = OpenWindowTags(NULL,
  2578.             WA_Width,    PALETTE_WIDTH,
  2579.             WA_Height,    PALETTE_HEIGHT,
  2580.  
  2581.             WA_Top,        (Screen -> Height - PALETTE_HEIGHT) >> 1,
  2582.             WA_Left,    (Screen -> Width - PALETTE_WIDTH) >> 1,
  2583.  
  2584.             WA_Activate,    TRUE,
  2585.             WA_DragBar,    TRUE,
  2586.             WA_CloseGadget, TRUE,
  2587.             WA_RMBTrap,    TRUE,
  2588.  
  2589.             WA_IDCMP,    IDCMP_CLOSEWINDOW | SLIDERIDCMP,
  2590.             WA_CustomScreen,Screen,
  2591.  
  2592.             WA_Title,    "Palette",
  2593.         TAG_DONE))
  2594.         {
  2595.             struct IntuiMessage    *Massage;
  2596.             ULONG             Class,Code;
  2597.             struct Gadget        *Gadget;
  2598.             BYTE             Terminated = FALSE;
  2599.             WORD             i;
  2600.  
  2601.             AddGList(Window,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  2602.             RefreshGList(GadgetList,Window,NULL,(UWORD)-1);
  2603.             GT_RefreshWindow(Window,NULL);
  2604.  
  2605.             if(DoCycle)
  2606.             {
  2607.                 DoCycle = FALSE;
  2608.  
  2609.                 LoadPalette(Screen,Palette,0);
  2610.             }
  2611.             else
  2612.                 DoCycle = FALSE;
  2613.  
  2614.             while(!Terminated)
  2615.             {
  2616.                 WaitPort(Window -> UserPort);
  2617.  
  2618.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort)))
  2619.                 {
  2620.                     Class    = Massage -> Class;
  2621.                     Code    = Massage -> Code;
  2622.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  2623.  
  2624.                     GT_ReplyIMsg(Massage);
  2625.  
  2626.                     if(Class == IDCMP_CLOSEWINDOW)
  2627.                         Terminated = TRUE;
  2628.  
  2629.                     if(Class == IDCMP_MOUSEMOVE)
  2630.                     {
  2631.                         WORD Wrap = (1 << Depth) - 2;
  2632.  
  2633.                         switch(Gadget -> GadgetID)
  2634.                         {
  2635.                             case 0:    RedLevel = Code;
  2636.                                 break;
  2637.  
  2638.                             case 1:    GreenLevel = Code;
  2639.                                 break;
  2640.  
  2641.                             case 2:    BlueLevel = Code;
  2642.                                 break;
  2643.                         }
  2644.  
  2645.                             /* Combine all three colour ranges into a single palette. */
  2646.  
  2647.                         for(i = 0 ; i < Wrap ; i++)
  2648.                             SetPaletteTriplet(Palette,Range[(RedLevel + i) % Wrap],Range[(GreenLevel + i) % Wrap],Range[(BlueLevel + i) % Wrap],2 + i);
  2649.  
  2650.                         LoadPalette(Screen,Palette,0);
  2651.                     }
  2652.                 }
  2653.             }
  2654.  
  2655.             CloseWindow(Window);
  2656.         }
  2657.     }
  2658.  
  2659.     FreeGadgets(GadgetList);
  2660. }
  2661.  
  2662.     /* MaxScrollPanel():
  2663.      *
  2664.      *    This routine implements the scroll amount control panel.
  2665.      */
  2666.  
  2667. VOID
  2668. MaxScrollPanel()
  2669. {
  2670.     struct Gadget    *GadgetList = NULL;
  2671.     struct Gadget    *GadgetArray[3];
  2672.     struct Window    *ScrollWindow;
  2673.  
  2674.     if(CreateAllScrollGadgets(&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
  2675.     {
  2676.         if(ScrollWindow = OpenWindowTags(NULL,
  2677.             WA_Width,    SCROLL_WIDTH,
  2678.             WA_Height,    SCROLL_HEIGHT,
  2679.  
  2680.             WA_Top,        (Screen -> Height - SCROLL_HEIGHT) >> 1,
  2681.             WA_Left,    (Screen -> Width - SCROLL_WIDTH) >> 1,
  2682.  
  2683.             WA_Activate,    TRUE,
  2684.             WA_DragBar,    TRUE,
  2685.             WA_DepthGadget,    TRUE,
  2686.             WA_CloseGadget,    TRUE,
  2687.             WA_RMBTrap,    TRUE,
  2688.             WA_CustomScreen,Screen,
  2689.  
  2690.             WA_IDCMP,    IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | BUTTONIDCMP | INTEGERIDCMP,
  2691.  
  2692.             WA_Title,    "Set scroll amount",
  2693.         TAG_DONE))
  2694.         {
  2695.             struct IntuiMessage    *Massage;
  2696.             ULONG             Class;
  2697.             struct Gadget        *Gadget;
  2698.             BYTE             Terminated = FALSE;
  2699.  
  2700.             AddGList(ScrollWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  2701.             RefreshGList(GadgetList,ScrollWindow,NULL,(UWORD)-1);
  2702.             GT_RefreshWindow(ScrollWindow,NULL);
  2703.  
  2704.             ActivateGadget(GadgetArray[0],ScrollWindow,NULL);
  2705.  
  2706.             while(!Terminated)
  2707.             {
  2708.                 WaitPort(ScrollWindow -> UserPort);
  2709.  
  2710.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(ScrollWindow -> UserPort)))
  2711.                 {
  2712.                     Class    = Massage -> Class;
  2713.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  2714.  
  2715.                     GT_ReplyIMsg(Massage);
  2716.  
  2717.                     if(Class == IDCMP_CLOSEWINDOW)
  2718.                         Terminated = TRUE;
  2719.  
  2720.                     if(Class == IDCMP_ACTIVEWINDOW)
  2721.                         ActivateGadget(GadgetArray[0],ScrollWindow,NULL);
  2722.  
  2723.                     if(Class == IDCMP_GADGETUP)
  2724.                     {
  2725.                         if(Gadget -> GadgetID == 2)
  2726.                             Terminated = TRUE;
  2727.                         else
  2728.                         {
  2729.                             LONG Value = ((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> LongInt;
  2730.                             BYTE GoodValue = TRUE;
  2731.  
  2732.                             if(Value < 1)
  2733.                             {
  2734.                                 GoodValue    = FALSE;
  2735.                                 Value        = 1;
  2736.                             }
  2737.  
  2738.                             if(Value >= Screen -> Width)
  2739.                             {
  2740.                                 GoodValue    = FALSE;
  2741.                                 Value        = Screen -> Width - 1;
  2742.                             }
  2743.  
  2744.                             if(GoodValue)
  2745.                             {
  2746.                                 MaxScroll    = (double)Value;
  2747.                                 Terminated    = TRUE;
  2748.                             }
  2749.                             else
  2750.                             {
  2751.                                 GT_SetGadgetAttrs(GadgetArray[0],ScrollWindow,NULL,
  2752.                                     GTIN_Number,Value,
  2753.                                 TAG_DONE);
  2754.  
  2755.                                 DisplayBeep(Screen);
  2756.  
  2757.                                 ActivateGadget(GadgetArray[0],ScrollWindow,NULL);
  2758.                             }
  2759.                         }
  2760.                     }
  2761.                 }
  2762.             }
  2763.  
  2764.             CloseWindow(ScrollWindow);
  2765.         }
  2766.     }
  2767.  
  2768.     FreeGadgets(GadgetList);
  2769. }
  2770.  
  2771.     /* AreaZoom():
  2772.      *
  2773.      *    This routine handles the selection of an area on screen
  2774.      *    to recalculate later.
  2775.      */
  2776.  
  2777. VOID
  2778. AreaZoom()
  2779. {
  2780.     struct IntuiMessage    *Massage;
  2781.     ULONG             Class,Code;
  2782.     UWORD             X,Y,
  2783.                  LastX,LastY;
  2784.  
  2785.     SetClear(Window);
  2786.  
  2787.     Code = NULL;
  2788.  
  2789.     Window -> Flags |= WFLG_RMBTRAP;
  2790.  
  2791.     ReportMouse(TRUE,Window);
  2792.  
  2793.     SetAPen(RPort,CurrentPen = (1 << Depth) - 1);
  2794.     SetDrMd(RPort,COMPLEMENT);
  2795.  
  2796.     LastX    = Window -> MouseX;
  2797.     LastY    = Window -> MouseY;
  2798.  
  2799.     DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1);
  2800.     DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY);
  2801.  
  2802.     do
  2803.     {
  2804.         WaitPort(Window -> UserPort);
  2805.  
  2806.         if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  2807.         {
  2808.             Class    = Massage -> Class;
  2809.             Code    = Massage -> Code;
  2810.  
  2811.             X    = Massage -> MouseX;
  2812.             Y    = Massage -> MouseY;
  2813.  
  2814.             ReplyMsg(&Massage -> ExecMessage);
  2815.  
  2816.             if(Class == IDCMP_MOUSEMOVE)
  2817.             {
  2818.                 if(LastX != X)
  2819.                 {
  2820.                     DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1);
  2821.                     DrawLine(RPort,X,0,X,Screen -> Height - 1);
  2822.                 }
  2823.  
  2824.                 if(LastY != Y)
  2825.                 {
  2826.                     DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY);
  2827.                     DrawLine(RPort,0,Y,Screen -> Width - 1,Y);
  2828.                 }
  2829.  
  2830.                 LastX = X;
  2831.                 LastY = Y;
  2832.             }
  2833.  
  2834.             if(Class == IDCMP_MOUSEBUTTONS)
  2835.             {
  2836.                 if(Code == SELECTDOWN)
  2837.                 {
  2838.                     UWORD    Left,Top,Width = 0,Height = 0;
  2839.                     BYTE    DidBox = FALSE;
  2840.  
  2841.                     Left    = X;
  2842.                     Top    = Y;
  2843.  
  2844.                     DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1);
  2845.                     DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY);
  2846.  
  2847.                     while(Code != SELECTUP)
  2848.                     {
  2849.                         WaitPort(Window -> UserPort);
  2850.  
  2851.                         while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  2852.                         {
  2853.                             Class    = Massage -> Class;
  2854.                             Code    = Massage -> Code;
  2855.  
  2856.                             Y    = Massage -> MouseY;
  2857.                             X    = Massage -> MouseX;
  2858.  
  2859.                             ReplyMsg(&Massage -> ExecMessage);
  2860.  
  2861.                             if(Class == IDCMP_MOUSEMOVE)
  2862.                             {
  2863.                                 if(Y > Top && X > Left)
  2864.                                 {
  2865.                                     if(DidBox)
  2866.                                     {
  2867.                                         Move(RPort,Left,Top);
  2868.                                         Draw(RPort,Left + Width - 1,Top);
  2869.                                         Draw(RPort,Left + Width - 1,Top + Height - 1);
  2870.                                         Draw(RPort,Left,Top + Height - 1);
  2871.                                         Draw(RPort,Left,Top + 1);
  2872.                                     }
  2873.  
  2874.                                     Width    = X - Left + 1;
  2875.                                     Height    = Y - Top + 1;
  2876.  
  2877.                                     Move(RPort,Left,Top);
  2878.                                     Draw(RPort,Left + Width - 1,Top);
  2879.                                     Draw(RPort,Left + Width - 1,Top + Height - 1);
  2880.                                     Draw(RPort,Left,Top + Height - 1);
  2881.                                     Draw(RPort,Left,Top + 1);
  2882.  
  2883.                                     DidBox = TRUE;
  2884.                                 }
  2885.  
  2886.                                 Code = NULL;
  2887.                             }
  2888.                         }
  2889.                     }
  2890.  
  2891.                     if(DidBox)
  2892.                     {
  2893.                         Move(RPort,Left,Top);
  2894.                         Draw(RPort,Left + Width - 1,Top);
  2895.                         Draw(RPort,Left + Width - 1,Top + Height - 1);
  2896.                         Draw(RPort,Left,Top + Height - 1);
  2897.                         Draw(RPort,Left,Top + 1);
  2898.                     }
  2899.  
  2900.                     SetDrMd(RPort,JAM1);
  2901.  
  2902.                     if(Width >= 2 && Height >= 2)
  2903.                     {
  2904.                         AreaLeft    = Left;
  2905.                         AreaTop        = Top;
  2906.  
  2907.                         AreaWidth    = Width;
  2908.                         AreaHeight    = Height;
  2909.  
  2910.                         NewCoords    = TRUE;
  2911.                         Running        = FALSE;
  2912.                         AreaActive    = TRUE;
  2913.                     }
  2914.                 }
  2915.             }
  2916.         }
  2917.     }
  2918.     while(Code != SELECTUP);
  2919.  
  2920.     ReportMouse(FALSE,Window);
  2921.  
  2922.     Window -> Flags &= ~WFLG_RMBTRAP;
  2923.  
  2924.     ClearPointer(Window);
  2925. }
  2926.  
  2927.     /* Zoom():
  2928.      *
  2929.      *    This routine handles the selection of an area on screen
  2930.      *    to zoom to later. Note that the area will be square.
  2931.      */
  2932.  
  2933. VOID
  2934. Zoom()
  2935. {
  2936.     struct IntuiMessage    *Massage;
  2937.     ULONG             Class,Code;
  2938.     UWORD             X,Y,
  2939.                  LastX,LastY;
  2940.  
  2941.     SetClear(Window);
  2942.  
  2943.     Code = NULL;
  2944.  
  2945.     Window -> Flags |= WFLG_RMBTRAP;
  2946.  
  2947.     ReportMouse(TRUE,Window);
  2948.  
  2949.     SetAPen(RPort,CurrentPen = (1 << Depth) - 1);
  2950.     SetDrMd(RPort,COMPLEMENT);
  2951.  
  2952.     LastX    = Window -> MouseX;
  2953.     LastY    = Window -> MouseY;
  2954.  
  2955.     DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1);
  2956.     DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY);
  2957.  
  2958.     while(Code != SELECTUP)
  2959.     {
  2960.         WaitPort(Window -> UserPort);
  2961.  
  2962.         if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  2963.         {
  2964.             Class    = Massage -> Class;
  2965.             Code    = Massage -> Code;
  2966.  
  2967.             X    = Massage -> MouseX;
  2968.             Y    = Massage -> MouseY;
  2969.  
  2970.             ReplyMsg(&Massage -> ExecMessage);
  2971.  
  2972.             if(Class == IDCMP_MOUSEMOVE)
  2973.             {
  2974.                 if(LastX != X)
  2975.                 {
  2976.                     DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1);
  2977.                     DrawLine(RPort,X,0,X,Screen -> Height - 1);
  2978.                 }
  2979.  
  2980.                 if(LastY != Y)
  2981.                 {
  2982.                     DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY);
  2983.                     DrawLine(RPort,0,Y,Screen -> Width - 1,Y);
  2984.                 }
  2985.  
  2986.                 LastX = X;
  2987.                 LastY = Y;
  2988.             }
  2989.  
  2990.             if(Class == IDCMP_MOUSEBUTTONS)
  2991.             {
  2992.                 if(Code == SELECTDOWN)
  2993.                 {
  2994.                     UWORD    Left,Top,
  2995.                         Width = 0,Height = 0;
  2996.                     BYTE    DidBox = FALSE;
  2997.  
  2998.                     DrawLine(RPort,LastX,0,LastX,Screen -> Height - 1);
  2999.                     DrawLine(RPort,0,LastY,Screen -> Width - 1,LastY);
  3000.  
  3001.                     Left    = X;
  3002.                     Top    = Y;
  3003.  
  3004.                     SetAPen(RPort,CurrentPen = (1 << Depth) - 1);
  3005.                     SetDrMd(RPort,COMPLEMENT);
  3006.  
  3007.                     while(Code != SELECTUP)
  3008.                     {
  3009.                         WaitPort(Window -> UserPort);
  3010.  
  3011.                         while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  3012.                         {
  3013.                             Class    = Massage -> Class;
  3014.                             Code    = Massage -> Code;
  3015.  
  3016.                             Y    = Massage -> MouseY;
  3017.  
  3018.                             ReplyMsg(&Massage -> ExecMessage);
  3019.  
  3020.                             if(Class == IDCMP_MOUSEMOVE)
  3021.                             {
  3022.                                 if(Y > Top)
  3023.                                 {
  3024.                                     if(DidBox)
  3025.                                     {
  3026.                                         Move(RPort,Left,Top);
  3027.                                         Draw(RPort,Left + Width - 1,Top);
  3028.                                         Draw(RPort,Left + Width - 1,Top + Height - 1);
  3029.                                         Draw(RPort,Left,Top + Height - 1);
  3030.                                         Draw(RPort,Left,Top + 1);
  3031.                                     }
  3032.  
  3033.                                     Width = Height = Y - Top + 1;
  3034.  
  3035.                                     Move(RPort,Left,Top);
  3036.                                     Draw(RPort,Left + Width - 1,Top);
  3037.                                     Draw(RPort,Left + Width - 1,Top + Height - 1);
  3038.                                     Draw(RPort,Left,Top + Height - 1);
  3039.                                     Draw(RPort,Left,Top + 1);
  3040.  
  3041.                                     DidBox = TRUE;
  3042.                                 }
  3043.  
  3044.                                 Code = NULL;
  3045.                             }
  3046.                         }
  3047.                     }
  3048.  
  3049.                     if(DidBox)
  3050.                     {
  3051.                         Move(RPort,Left,Top);
  3052.                         Draw(RPort,Left + Width - 1,Top);
  3053.                         Draw(RPort,Left + Width - 1,Top + Height - 1);
  3054.                         Draw(RPort,Left,Top + Height - 1);
  3055.                         Draw(RPort,Left,Top + 1);
  3056.                     }
  3057.  
  3058.                     SetDrMd(RPort,JAM1);
  3059.  
  3060.                     if(Width >= 2 && Height >= 2)
  3061.                     {
  3062.                         BYTE Val;
  3063.  
  3064.                         SetWait(Window);
  3065.  
  3066.                         if(AnimRunning)
  3067.                             Val = MyEasyRequest("Yes|Abort|No","Transition will consist\nof %ld images.\n\nDo you wish to use the\ncurrent coordinates?",CalculateFrames(MinReal + (double)Left * RealStep,MinImaginary + (double)Top * ImaginaryStep,(double)Width * RealStep));
  3068.                         else
  3069.                             Val = MyEasyRequest("Yes|No","Do you wish to use the\ncurrent coordinates?");
  3070.  
  3071.                         switch(Val)
  3072.                         {
  3073.                             case 0:    break;
  3074.  
  3075.                             case 1:    MinReal        = MinReal + (double)Left * RealStep;
  3076.                                 MinImaginary    = MinImaginary + (double)Top * ImaginaryStep;
  3077.  
  3078.                                 RealWidth    = (double)Width * RealStep;
  3079.                                 ImaginaryHeight    = (double)Height * ImaginaryStep;
  3080.  
  3081.                                 RealStep    = RealWidth / (double)Window -> Width;
  3082.                                 ImaginaryStep    = ImaginaryHeight / (double)Window -> Height;
  3083.  
  3084.                                 MainMinReal        = MinReal;
  3085.                                 MainMinImaginary    = MinImaginary;
  3086.                                 MainRealWidth        = RealWidth;
  3087.                                 MainImaginaryHeight    = ImaginaryHeight;
  3088.  
  3089.                                 NewCoords    = TRUE;
  3090.                                 Running        = FALSE;
  3091.                                 AreaActive    = FALSE;
  3092.                                 break;
  3093.  
  3094.                             case 2:    Running = FALSE;
  3095.                                 StopAnim();
  3096.                                 break;
  3097.                         }
  3098.                     }
  3099.                 }
  3100.             }
  3101.         }
  3102.     }
  3103.  
  3104.     ReportMouse(FALSE,Window);
  3105.  
  3106.     Window -> Flags &= ~WFLG_RMBTRAP;
  3107.  
  3108.     ClearPointer(Window);
  3109. }
  3110.  
  3111.     /* HandleEvent():
  3112.      *
  3113.      *    The global input event (menus, key, mouse, etc.) handler.
  3114.      */
  3115.  
  3116. VOID
  3117. HandleEvent()
  3118. {
  3119.     struct IntuiMessage    *Massage;
  3120.     struct MenuItem        *Item;
  3121.     ULONG             Class,
  3122.                  Code,
  3123.                  MenuItem,
  3124.                  Selected;
  3125.     UBYTE            *DummyChar;
  3126.     BYTE             Waiting = FALSE;
  3127.     MandelHeader         Mandel;
  3128.  
  3129.     do
  3130.     {
  3131.         while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  3132.         {
  3133.             Class    = Massage -> Class;
  3134.             Code    = Massage -> Code;
  3135.  
  3136.             ReplyMsg(&Massage -> ExecMessage);
  3137.  
  3138.             if(Class == IDCMP_MENUVERIFY)
  3139.                 Waiting = HoldIt = TRUE;
  3140.  
  3141.             if(Class == IDCMP_VANILLAKEY)
  3142.             {
  3143.                 if(Code == '\t')
  3144.                 {
  3145.                     if(!DoCycle)
  3146.                     {
  3147.                         Forward = TRUE;
  3148.  
  3149.                         DoCycle = TRUE;
  3150.                     }
  3151.                     else
  3152.                         DoCycle = FALSE;
  3153.                 }
  3154.             }
  3155.  
  3156.             if(Class == IDCMP_RAWKEY)
  3157.             {
  3158.                 if(Code == CURSORLEFT)
  3159.                     CycleColours(TRUE);
  3160.  
  3161.                 if(Code == CURSORRIGHT)
  3162.                     CycleColours(FALSE);
  3163.  
  3164.                 if(Code == CURSORUP)
  3165.                 {
  3166.                     Forward = TRUE;
  3167.  
  3168.                     DoCycle = TRUE;
  3169.                 }
  3170.  
  3171.                 if(Code == CURSORDOWN)
  3172.                 {
  3173.                     Forward = FALSE;
  3174.  
  3175.                     DoCycle = TRUE;
  3176.                 }
  3177.             }
  3178.  
  3179.             if(Class == IDCMP_MENUPICK)
  3180.             {
  3181.                 Waiting = HoldIt = FALSE;
  3182.  
  3183.                 if(GotClip)
  3184.                 {
  3185.                     BltBitMap(BackupBitMap,0,0,RPort -> BitMap,(Square - 25 * 8) >> 1,(Square - 8) >> 1,8 * 25,8,0xC0,0xFF,NULL);
  3186.  
  3187.                     GotClip = FALSE;
  3188.                 }
  3189.  
  3190.                 MenuItem = Code;
  3191.  
  3192.                 while(MenuItem != MENUNULL)
  3193.                 {
  3194.                     if(Item = ItemAddress(Menu,MenuItem))
  3195.                     {
  3196.                         Selected = (ULONG)MENU_USERDATA(Item);
  3197.  
  3198.                         switch(Selected)
  3199.                         {
  3200.                             case MEN_OPEN:    BlockWindow();
  3201.  
  3202.                                     strcpy(NameBuffer,LastName);
  3203.  
  3204.                                     DummyChar = PathPart(NameBuffer);
  3205.  
  3206.                                     *DummyChar = 0;
  3207.  
  3208.                                     if(GetFile("Open picture",NameBuffer,FilePart(LastName),NameBuffer,"~(#?.info)",FALSE))
  3209.                                     {
  3210.                                         struct PictureInfo *Info;
  3211.  
  3212.                                         if(Info = LoadPicture(NameBuffer))
  3213.                                         {
  3214.                                             if(ModeNotAvailable(Info -> ViewModes) || (Info -> BitMapHeader . nPlanes > 5 && !Is39))
  3215.                                                 MyEasyRequest("Continue","Cannot display this image.");
  3216.                                             else
  3217.                                             {
  3218.                                                 if(Info -> BitMapHeader . w == Screen -> Width && Info -> BitMapHeader . h == Screen -> Height && Info -> BitMapHeader . nPlanes == Depth)
  3219.                                                 {
  3220.                                                     LONG i,Size;
  3221.     
  3222.                                                     DoCycle = FALSE;
  3223.     
  3224.                                                     Size = GetPaletteSize(Palette);
  3225.     
  3226.                                                     for(i = 0 ; i < Size ; i++)
  3227.                                                         SetPaletteEntry(Palette,0,i);
  3228.     
  3229.                                                     LoadPalette(Screen,Palette,0);
  3230.     
  3231.                                                     BltBitMapRastPort(Info -> BitMap,0,0,RPort,0,0,Square,Square,0xC0);
  3232.     
  3233.                                                     LoadPalette(Screen,Info -> Palette,0);
  3234.                                                     GetPalette(Screen,Palette);
  3235.     
  3236.                                                     if(Info -> MandelHeader . Iterations)
  3237.                                                     {
  3238.                                                         MainMinReal        = MinReal        = Info -> MandelHeader . MinReal;
  3239.                                                         MainMinImaginary    = MinImaginary        = Info -> MandelHeader . MinImaginary;
  3240.                                                         MainRealWidth        = RealWidth        = Info -> MandelHeader . RealWidth;
  3241.                                                         MainImaginaryHeight    = ImaginaryHeight    = Info -> MandelHeader . ImaginaryHeight;
  3242.                                                         MaxIteration                    = Info -> MandelHeader . Iterations - 1;
  3243.     
  3244.                                                         IterationSetup();
  3245.     
  3246.                                                         RealStep    = RealWidth / (double)Window -> Width;
  3247.                                                         ImaginaryStep    = ImaginaryHeight / (double)Window -> Height;
  3248.                                                     }
  3249.                                                     else
  3250.                                                         MyEasyRequest("Continue","Could not read image\ncoordinates, previous values\nremain untouched.");
  3251.     
  3252.                                                     strcpy(LastName,NameBuffer);
  3253.     
  3254.                                                     Running = FALSE;
  3255.     
  3256.                                                     AreaActive = FALSE;
  3257.                                                 }
  3258.                                                 else
  3259.                                                 {
  3260.                                                     if(Info -> BitMapHeader . w == Info -> BitMapHeader . h && Info -> MandelHeader . Iterations)
  3261.                                                     {
  3262.                                                         MainMinReal        = MinReal        = Info -> MandelHeader . MinReal;
  3263.                                                         MainMinImaginary    = MinImaginary        = Info -> MandelHeader . MinImaginary;
  3264.                                                         MainRealWidth        = RealWidth        = Info -> MandelHeader . RealWidth;
  3265.                                                         MainImaginaryHeight    = ImaginaryHeight    = Info -> MandelHeader . ImaginaryHeight;
  3266.                                                         MaxIteration                    = Info -> MandelHeader . Iterations - 1;
  3267.  
  3268.                                                         RealStep        = RealWidth / (double)Window -> Width;
  3269.                                                         ImaginaryStep        = ImaginaryHeight / (double)Window -> Height;
  3270.  
  3271.                                                         strcpy(LastName,NameBuffer);
  3272.  
  3273.                                                         Running        = FALSE;
  3274.                                                         AreaActive    = FALSE;
  3275.                                                         NewMode        = TRUE;
  3276.                                                         DoCycle        = FALSE;
  3277.  
  3278.                                                         GlobalBitMap    = Info -> BitMap;
  3279.                                                         GlobalSize    = Info -> BitMapHeader . w;
  3280.                                                         GlobalDepth    = Info -> BitMapHeader . nPlanes;
  3281.                                                         GlobalMode    = Info -> ViewModes;
  3282.                                                         GlobalPalette    = Info -> Palette;
  3283.  
  3284.                                                         Info -> BitMap    = NULL;
  3285.                                                         Info -> Palette    = NULL;
  3286.                                                     }
  3287.                                                     else
  3288.                                                         MyEasyRequest("Continue","Picture has wrong size!");
  3289.                                                 }
  3290.                                             }
  3291.  
  3292.                                             FreePicture(Info);
  3293.                                         }
  3294.                                         else
  3295.                                             MyEasyRequest("Continue","Error reading file\n%s.",FilePart(NameBuffer));
  3296.                                     }
  3297.  
  3298.                                     ReleaseWindow();
  3299.  
  3300.                                     break;
  3301.  
  3302.                             case MEN_SAVE:    BlockWindow();
  3303.  
  3304.                                     if(NameBuffer[0])
  3305.                                         goto SaveIt;
  3306.  
  3307.                             case MEN_SAVEAS:BlockWindow();
  3308.  
  3309.                                     strcpy(NameBuffer,LastName);
  3310.  
  3311.                                     DummyChar = PathPart(NameBuffer);
  3312.  
  3313.                                     *DummyChar = 0;
  3314.  
  3315.                                     if(GetFile("Save picture as",NameBuffer,FilePart(LastName),NameBuffer,"~(#?.info)",TRUE))
  3316.                                     {
  3317. SaveIt:                                        Mandel . MinReal        = MinReal;
  3318.                                         Mandel . MinImaginary        = MinImaginary;
  3319.                                         Mandel . RealWidth        = RealWidth;
  3320.                                         Mandel . ImaginaryHeight    = ImaginaryHeight;
  3321.                                         Mandel . Iterations        = MaxIteration + 1;
  3322.  
  3323.                                         if(!SavePicture(NameBuffer,Screen,&Mandel))
  3324.                                             MyEasyRequest("Continue","Could not save file\n%s.",FilePart(NameBuffer));
  3325.                                         else
  3326.                                         {
  3327.                                             if(!ThisProcess -> pr_CLI)
  3328.                                                 PutDiskObject(NameBuffer,&PictureIcon);
  3329.  
  3330.                                             strcpy(LastName,NameBuffer);
  3331.                                         }
  3332.                                     }
  3333.  
  3334.                                     ReleaseWindow();
  3335.                                     break;
  3336.  
  3337.                             case MEN_PRI0:    SetTaskPri(ThisProcess,-5);
  3338.                                     break;
  3339.  
  3340.                             case MEN_PRI1:    SetTaskPri(ThisProcess,0);
  3341.                                     break;
  3342.  
  3343.                             case MEN_PRI2:    SetTaskPri(ThisProcess,5);
  3344.                                     break;
  3345.  
  3346.                             case MEN_PLAY:    BlockWindow();
  3347.  
  3348.                                     ReplayAnim();
  3349.  
  3350.                                     ReleaseWindow();
  3351.  
  3352.                                     break;
  3353.  
  3354.                             case MEN_START:    if(!AnimRunning)
  3355.                                     {
  3356.                                         Running        = FALSE;
  3357.                                         FullPicture    = FALSE;
  3358.                                         AnimRunning    = TRUE;
  3359.                                     }
  3360.  
  3361.                                     break;
  3362.  
  3363.                             case MEN_STOP:    BlockWindow();
  3364.  
  3365.                                     StopAnim();
  3366.  
  3367.                                     Running = FALSE;
  3368.  
  3369.                                     FullPicture = FALSE;
  3370.  
  3371.                                     ReleaseWindow();
  3372.  
  3373.                                     break;
  3374.  
  3375.                             case MEN_SCROLL:BlockWindow();
  3376.  
  3377.                                     MaxScrollPanel();
  3378.  
  3379.                                     ReleaseWindow();
  3380.  
  3381.                                     break;
  3382.  
  3383.                             case MEN_FRAME:    if(Item -> Flags & CHECKED)
  3384.                                         Frame = TRUE;
  3385.                                     else
  3386.                                         Frame = FALSE;
  3387.  
  3388.                                     break;
  3389.  
  3390.                             case MEN_INCLUDE:
  3391.                                     if(Item -> Flags & CHECKED)
  3392.                                         Include = TRUE;
  3393.                                     else
  3394.                                         Include = FALSE;
  3395.  
  3396.                                     break;
  3397.  
  3398.                             case MEN_RESOLUTION:
  3399.                                     if(AslBase -> lib_Version >= 38)
  3400.                                     {
  3401.                                         ULONG DisplayMode = GetVPModeID(&Screen -> ViewPort);
  3402.  
  3403.                                         BlockWindow();
  3404.  
  3405.                                         if(SelectDisplayMode(Window,&DisplayMode))
  3406.                                         {
  3407.                                             if(DisplayMode != GetVPModeID(&Screen -> ViewPort))
  3408.                                             {
  3409.                                                 Mode    = DisplayMode;
  3410.                                                 NewMode = TRUE;
  3411.                                                 Running = FALSE;
  3412.                                                 DoCycle = FALSE;
  3413.                                             }
  3414.                                         }
  3415.  
  3416.                                         ReleaseWindow();
  3417.                                     }
  3418.                                     else
  3419.                                     {
  3420.                                         NewMode = TRUE;
  3421.                                         Running = FALSE;
  3422.                                         DoCycle = FALSE;
  3423.  
  3424.                                         if(Mode == LORES_KEY)
  3425.                                         {
  3426.                                             Mode    = HIRESLACE_KEY;
  3427.                                             Depth    = 4;
  3428.                                         }
  3429.                                         else
  3430.                                         {
  3431.                                             Mode    = LORES_KEY;
  3432.                                             Depth    = 5;
  3433.                                         }
  3434.                                     }
  3435.  
  3436.                                     if(NewMode)
  3437.                                     {
  3438.                                         MainMinReal        = MinReal;
  3439.                                         MainMinImaginary    = MinImaginary;
  3440.                                         MainRealWidth        = RealWidth;
  3441.                                         MainImaginaryHeight    = ImaginaryHeight;
  3442.                                     }
  3443.  
  3444.                                     break;
  3445.  
  3446.                             case MEN_ABOUT:    BlockWindow();
  3447.  
  3448.                                     MyEasyRequest("So what?","         Mandel²\n\nYet another Mandelbrot set\n   exploration program\n\n        Written by\n   Olaf `Olsen' Barthel\n\n  © Copyright 1991-1992\n");
  3449.  
  3450.                                     ReleaseWindow();
  3451.                                     break;
  3452.  
  3453.                             case MEN_QUIT:    BlockWindow();
  3454.  
  3455.                                     if(MyEasyRequest("Yes|No","Do you really wish to\nleave this program?"))
  3456.                                         CloseAll(RETURN_OK);
  3457.  
  3458.                                     ReleaseWindow();
  3459.                                     break;
  3460.  
  3461.                             case MEN_ZOOM:    Zoom();
  3462.                                     break;
  3463.  
  3464.                             case MEN_CLIP:    AreaZoom();
  3465.                                     Faster = TRUE;
  3466.                                     break;
  3467.  
  3468.                             case MEN_RERUN:    AreaZoom();
  3469.                                     Faster = FALSE;
  3470.                                     break;
  3471.  
  3472.                             case MEN_PRECISE:
  3473.                                     if(Item -> Flags & CHECKED)
  3474.                                         Precise = TRUE;
  3475.                                     else
  3476.                                         Precise = FALSE;
  3477.  
  3478.                                     break;
  3479.  
  3480.                             case MEN_COORDS:BlockWindow();
  3481.                                     Coords();
  3482.                                     ReleaseWindow();
  3483.                                     break;
  3484.  
  3485.                             case MEN_PALETTE:
  3486.                                     BlockWindow();
  3487.                                     AdjustPalette();
  3488.                                     ReleaseWindow();
  3489.                                     break;
  3490.  
  3491.                             case MEN_RUN:    Running ^= TRUE;
  3492.  
  3493.                                     if(!Running)
  3494.                                         FullPicture = FALSE;
  3495.  
  3496.                                     break;
  3497.  
  3498.                             default:    if(Selected >= 1 && Selected <= 16)
  3499.                                         MaxIteration = (1 << Selected) - 1;
  3500.  
  3501.                                     break;
  3502.                         }
  3503.  
  3504.                         MenuItem = Item -> NextSelect;
  3505.                     }
  3506.                     else
  3507.                         break;
  3508.                 }
  3509.             }
  3510.         }
  3511.  
  3512.         if(Waiting)
  3513.             WaitPort(Window -> UserPort);
  3514.     }
  3515.     while(Waiting);
  3516. }
  3517.  
  3518.     /* Mandelbrot():
  3519.      *
  3520.      *    The recursive image generation routine.
  3521.      */
  3522.  
  3523. VOID
  3524. Mandelbrot(double MinReal,double MinImaginary,double RealStep,double ImaginaryStep,LONG Left,LONG Top,LONG Width,LONG Height)
  3525. {
  3526.     if(CheckSignal(SIG_WINDOW))
  3527.         HandleEvent();
  3528.  
  3529.     if(Running)
  3530.     {
  3531.         BYTE    Colours[4],
  3532.             LastColour,
  3533.             Ident = TRUE;
  3534.         WORD    Positions[4][2],
  3535.             i;
  3536.  
  3537.             /* Set up pixel positions. */
  3538.  
  3539.         Positions[0][0] = Left;
  3540.         Positions[0][1] = Top;
  3541.  
  3542.         Positions[1][0] = Left + Width - 1;
  3543.         Positions[1][1] = Top;
  3544.  
  3545.         Positions[2][0] = Left + Width - 1;
  3546.         Positions[2][1] = Top + Height - 1;
  3547.  
  3548.         Positions[3][0] = Left;
  3549.         Positions[3][1] = Top + Height - 1;
  3550.  
  3551.         for(i = 0 ; i < 4 ; i++)
  3552.         {
  3553.                 /* Calculate colour values for each pixel. */
  3554.  
  3555.             Colours[i] = Iterate(MinReal + RealStep * (double)Positions[i][0],MinImaginary + ImaginaryStep * (double)Positions[i][1]);
  3556.  
  3557.                 /* Are all colour identical? */
  3558.  
  3559.             if(Ident)
  3560.             {
  3561.                 if(!i)
  3562.                     LastColour = Colours[i];
  3563.                 else
  3564.                 {
  3565.                     if(Colours[i] != LastColour)
  3566.                         Ident = FALSE;
  3567.                     else
  3568.                         LastColour = Colours[i];
  3569.                 }
  3570.             }
  3571.         }
  3572.  
  3573.             /* If all colour happen to be identical, fill the
  3574.              * are in the given colour.
  3575.              */
  3576.  
  3577.         if(Ident)
  3578.         {
  3579.                 /* If extra precision is selected, also check
  3580.                  * if all the pixels on the margin of the
  3581.                  * current square are in the same colour.
  3582.                  */
  3583.  
  3584.             if(Precise)
  3585.             {
  3586.                 WORD    PositionBackup[4][2],
  3587.                     j;
  3588.  
  3589.                 CopyMem(Positions,PositionBackup,sizeof(PositionBackup));
  3590.  
  3591.                 for(i = 0 ; i < Width - 1 ; i++)
  3592.                 {
  3593.                     PositionBackup[0][0]++;
  3594.                     PositionBackup[1][1]++;
  3595.                     PositionBackup[2][0]--;
  3596.                     PositionBackup[3][1]--;
  3597.  
  3598.                     for(j = 0 ; j < 4 ; j++)
  3599.                     {
  3600.                         if(Iterate(MinReal + RealStep * (double)PositionBackup[j][0],MinImaginary + ImaginaryStep * (double)PositionBackup[j][1]) != Colours[0])
  3601.                             goto Full;
  3602.                     }
  3603.                 }
  3604.             }
  3605.  
  3606.                 /* If necessary fill the square. */
  3607.  
  3608.             if(Colours[0])
  3609.             {
  3610.                 if(CurrentPen != Colours[0])
  3611.                     SetAPen(RPort,CurrentPen = Colours[0]);
  3612.  
  3613.                 RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
  3614.             }
  3615.         }
  3616.         else
  3617.         {
  3618.                 /* If not already down at minimum level,
  3619.                  * split the square again.
  3620.                  */
  3621.  
  3622. Full:            if(Width > 2 && Height > 2)
  3623.             {
  3624.                 Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Left,Top,Width >> 1,Height >> 1);
  3625.                 Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Left + (Width >> 1),Top,Width >> 1,Height >> 1);
  3626.  
  3627.                 Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Left,Top + (Height >> 1),Width >> 1,Height >> 1);
  3628.                 Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Left + (Width >> 1),Top + (Height >> 1),Width >> 1,Height >> 1);
  3629.             }
  3630.             else
  3631.             {
  3632.                 if(IsNative)
  3633.                 {
  3634.                     register struct BitMap *BitMap = RPort -> BitMap;
  3635.  
  3636.                         /* Set the pixels. */
  3637.  
  3638.                     for(i = 0 ; i < 4 ; i++)
  3639.                     {
  3640.                         if(Colours[i])
  3641.                             Plot(BitMap,Positions[i][0],Positions[i][1],Colours[i]);
  3642.                     }
  3643.                 }
  3644.                 else
  3645.                 {
  3646.                         /* Set the pixels. */
  3647.  
  3648.                     for(i = 0 ; i < 4 ; i++)
  3649.                     {
  3650.                         if(Colours[i])
  3651.                         {
  3652.                             if(CurrentPen != Colours[i])
  3653.                                 SetAPen(RPort,CurrentPen = Colours[i]);
  3654.  
  3655.                             WritePixel(RPort,Positions[i][0],Positions[i][1]);
  3656.                         }
  3657.                     }
  3658.                 }
  3659.             }
  3660.         }
  3661.     }
  3662. }
  3663.  
  3664.     /* RunMandelbrot():
  3665.      *
  3666.      *    This is the recursive image generation driver, it
  3667.      *    remembers the time it took to generate the image and
  3668.      *    calls the recursive image generation routine.
  3669.      */
  3670.  
  3671. VOID
  3672. RunMandelbrot(double MinReal,double MaxReal,double MinImaginary,double MaxImaginary,LONG Width,LONG Height)
  3673. {
  3674.     double        RealStep,ImaginaryStep;
  3675.     UBYTE        TimeBuffer[40];
  3676.     struct timeval    TimeVal;
  3677.  
  3678.     GetTime();
  3679.  
  3680.     TimeVal = TimeRequest -> tr_time;
  3681.  
  3682.     RealStep    = (MaxReal - MinReal) / (double)Width;
  3683.     ImaginaryStep    = (MaxImaginary - MinImaginary) / (double)Height;
  3684.  
  3685.     if(Is39)
  3686.         CurrentPen = GetAPen(RPort);
  3687.     else
  3688.         CurrentPen = RPort -> FgPen;
  3689.  
  3690.     FullPicture = TRUE;
  3691.  
  3692.     Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,0,0,Window -> Width >> 1,Window -> Height >> 1);
  3693.     Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Window -> Width >> 1,0,Window -> Width >> 1,Window -> Height >> 1);
  3694.  
  3695.     Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,0,Window -> Height >> 1,Window -> Width >> 1,Window -> Height >> 1);
  3696.     Mandelbrot(MinReal,MinImaginary,RealStep,ImaginaryStep,Window -> Width >> 1,Window -> Height >> 1,Window -> Width >> 1,Window -> Height >> 1);
  3697.  
  3698.     GetTime();
  3699.  
  3700.     SubTime(&TimeRequest -> tr_time,&TimeVal);
  3701.  
  3702.     BltBitMap(RPort -> BitMap,(Square - 25 * 8) >> 1,(Square - 8) >> 1,BackupBitMap,0,0,8 * 25,8,0xC0,0xFF,NULL);
  3703.  
  3704.     GotClip = TRUE;
  3705.  
  3706.     SetAPen(RPort,CurrentPen = 1);
  3707.     SetDrMd(RPort,JAM1);
  3708.  
  3709.     TimeVal = TimeRequest -> tr_time;
  3710.  
  3711.     sprintf(TimeBuffer,"Duration %2d:%02d:%02d Minutes",(TimeVal . tv_secs % 86400) / 3600,(TimeVal . tv_secs % 3600) / 60,TimeVal . tv_secs % 60);
  3712.  
  3713.     Move(RPort,(Square - 25 * 8) >> 1,((Square - 8) >> 1) + 6);
  3714.     Text(RPort,TimeBuffer,25);
  3715.  
  3716.     Running = FALSE;
  3717. }
  3718.  
  3719.     /* RunAreaMandelbrot(double RealStep,double ImaginaryStep):
  3720.      *
  3721.      *    This is the iterative image generation routine,
  3722.      *    unlike the routines above it generates the image
  3723.      *    pixel by pixel and is not limited to a square
  3724.      *    drawing area.
  3725.      */
  3726.  
  3727. VOID
  3728. RunAreaMandelbrot(double RealStep,double ImaginaryStep)
  3729. {
  3730.     double        RealValue,
  3731.             ImaginaryValue;
  3732.     WORD        x,y;
  3733.     UBYTE        TimeBuffer[40];
  3734.     struct timeval    TimeVal;
  3735.     BYTE        Colour;
  3736.  
  3737.     if(Is39)
  3738.         CurrentPen = GetAPen(RPort);
  3739.     else
  3740.         CurrentPen = RPort -> FgPen;
  3741.  
  3742.     GetTime();
  3743.  
  3744.     TimeVal = TimeRequest -> tr_time;
  3745.  
  3746.     ImaginaryValue = MinImaginary + ImaginaryStep * (double)AreaTop;
  3747.  
  3748.         /* `Faster' actually only means that before a pixel
  3749.          * is drawn the approriate spot is checked to see
  3750.          * if there is not already a pixel in place.
  3751.          */
  3752.  
  3753.     if(IsNative)
  3754.     {
  3755.         struct BitMap *BitMap = RPort -> BitMap;
  3756.  
  3757.         if(Faster)
  3758.         {
  3759.             for(y = 0 ; (y < AreaHeight) && Running ; y++)
  3760.             {
  3761.                 RealValue = MinReal + RealStep * (double)AreaLeft;
  3762.     
  3763.                 for(x = 0 ; (x < AreaWidth) && Running ; x++)
  3764.                 {
  3765.                     if(!Test(BitMap,AreaLeft + x,AreaTop + y))
  3766.                     {
  3767.                         if((Colour = Iterate(RealValue,ImaginaryValue)))
  3768.                             Plot(BitMap,AreaLeft + x,AreaTop + y,Colour);
  3769.                     }
  3770.     
  3771.                     RealValue += RealStep;
  3772.     
  3773.                     if(CheckSignal(SIG_WINDOW))
  3774.                         HandleEvent();
  3775.                 }
  3776.     
  3777.                 ImaginaryValue += ImaginaryStep;
  3778.             }
  3779.         }
  3780.         else
  3781.         {
  3782.                 /* These loops will calculate the image pixel
  3783.                  * by pixel without skipping already set areas.
  3784.                  * The first check insures that the drawing area
  3785.                  * is as wide as the screen which means that
  3786.                  * we are able to generate the pixels in fast
  3787.                  * ram and to copy them to chip ram when done.
  3788.                  */
  3789.     
  3790.             if(AreaWidth == Window -> Width && LineBitMap . Planes[0])
  3791.             {
  3792.                 BitMap = &LineBitMap;
  3793.     
  3794.                 for(y = 0 ; (y < AreaHeight) && Running ; y++)
  3795.                 {
  3796.                     RealValue = MinReal + RealStep * (double)AreaLeft;
  3797.     
  3798.                     for(x = 0 ; (x < AreaWidth) && Running ; x++)
  3799.                     {
  3800.                         if((Colour = Iterate(RealValue,ImaginaryValue)))
  3801.                             Plot(BitMap,AreaLeft + x,0,Colour);
  3802.                         else
  3803.                             Plot(BitMap,AreaLeft + x,0,0);
  3804.     
  3805.                         RealValue += RealStep;
  3806.     
  3807.                         if(CheckSignal(SIG_WINDOW))
  3808.                             HandleEvent();
  3809.                     }
  3810.     
  3811.                     if(Running)
  3812.                         CopyLine(BitMap,AreaTop + y);
  3813.     
  3814.                     ImaginaryValue += ImaginaryStep;
  3815.                 }
  3816.             }
  3817.             else
  3818.             {
  3819.                 for(y = 0 ; (y < AreaHeight) && Running ; y++)
  3820.                 {
  3821.                     RealValue = MinReal + RealStep * (double)AreaLeft;
  3822.     
  3823.                     for(x = 0 ; (x < AreaWidth) && Running ; x++)
  3824.                     {
  3825.                         if((Colour = Iterate(RealValue,ImaginaryValue)))
  3826.                             Plot(BitMap,AreaLeft + x,AreaTop + y,Colour);
  3827.     
  3828.                         RealValue += RealStep;
  3829.     
  3830.                         if(CheckSignal(SIG_WINDOW))
  3831.                             HandleEvent();
  3832.                     }
  3833.     
  3834.                     ImaginaryValue += ImaginaryStep;
  3835.                 }
  3836.             }
  3837.         }
  3838.     }
  3839.     else
  3840.     {
  3841.         if(Faster)
  3842.         {
  3843.             for(y = 0 ; (y < AreaHeight) && Running ; y++)
  3844.             {
  3845.                 RealValue = MinReal + RealStep * (double)AreaLeft;
  3846.     
  3847.                 for(x = 0 ; (x < AreaWidth) && Running ; x++)
  3848.                 {
  3849.                     if(!ReadPixel(RPort,AreaLeft + x,AreaTop + y))
  3850.                     {
  3851.                         if((Colour = Iterate(RealValue,ImaginaryValue)))
  3852.                         {
  3853.                             if(CurrentPen != Colour)
  3854.                                 SetAPen(RPort,CurrentPen = Colour);
  3855.  
  3856.                             WritePixel(RPort,AreaLeft + x,AreaTop + y);
  3857.                         }
  3858.                     }
  3859.     
  3860.                     RealValue += RealStep;
  3861.     
  3862.                     if(CheckSignal(SIG_WINDOW))
  3863.                         HandleEvent();
  3864.                 }
  3865.     
  3866.                 ImaginaryValue += ImaginaryStep;
  3867.             }
  3868.         }
  3869.         else
  3870.         {
  3871.             for(y = 0 ; (y < AreaHeight) && Running ; y++)
  3872.             {
  3873.                 RealValue = MinReal + RealStep * (double)AreaLeft;
  3874.  
  3875.                 for(x = 0 ; (x < AreaWidth) && Running ; x++)
  3876.                 {
  3877.                     if((Colour = Iterate(RealValue,ImaginaryValue)))
  3878.                     {
  3879.                         if(CurrentPen != Colour)
  3880.                             SetAPen(RPort,CurrentPen = Colour);
  3881.  
  3882.                         WritePixel(RPort,AreaLeft + x,AreaTop + y);
  3883.                     }
  3884.  
  3885.                     RealValue += RealStep;
  3886.  
  3887.                     if(CheckSignal(SIG_WINDOW))
  3888.                         HandleEvent();
  3889.                 }
  3890.  
  3891.                 ImaginaryValue += ImaginaryStep;
  3892.             }
  3893.         }
  3894.     }
  3895.  
  3896.     GetTime();
  3897.  
  3898.     SubTime(&TimeRequest -> tr_time,&TimeVal);
  3899.  
  3900.     BltBitMap(RPort -> BitMap,(Square - 25 * 8) >> 1,(Square - 8) >> 1,BackupBitMap,0,0,8 * 25,8,0xC0,0xFF,NULL);
  3901.  
  3902.     GotClip = TRUE;
  3903.  
  3904.     SetAPen(RPort,CurrentPen = 1);
  3905.     SetDrMd(RPort,JAM1);
  3906.  
  3907.     TimeVal = TimeRequest -> tr_time;
  3908.  
  3909.     sprintf(TimeBuffer,"Duration %2d:%02d:%02d Minutes",(TimeVal . tv_secs % 86400) / 3600,(TimeVal . tv_secs % 3600) / 60,TimeVal . tv_secs % 60);
  3910.  
  3911.     Move(RPort,(Square - 25 * 8) >> 1,((Square - 8) >> 1) + 6);
  3912.     Text(RPort,TimeBuffer,25);
  3913.  
  3914.     Running = FALSE;
  3915.  
  3916.     Faster = TRUE;
  3917. }
  3918.  
  3919.     /* main():
  3920.      *
  3921.      *    The notorious main routine.
  3922.      */
  3923.  
  3924. VOID __stdargs
  3925. main()
  3926. {
  3927.     struct PictureInfo    *Info;
  3928.     BYTE             GotImage    = FALSE,
  3929.                  IsAnim        = FALSE;
  3930.  
  3931.         /* Open the required resources. */
  3932.  
  3933.     OpenAll();
  3934.  
  3935.     MinReal        = -RealWidth / 2;
  3936.     MinImaginary    = -ImaginaryHeight / 2;
  3937.  
  3938.     DummyBuffer[0] = 0;
  3939.  
  3940.         /* Pick up any selected images if run from Workbench. */
  3941.  
  3942.     if(!ThisProcess -> pr_CLI)
  3943.     {
  3944.         extern struct WBStartup *WBenchMsg;
  3945.  
  3946.         DefaultTool[0] = 0;
  3947.  
  3948.             /* Build new default tool name. */
  3949.  
  3950.         if(NameFromLock(WBenchMsg -> sm_ArgList[0] . wa_Lock,DefaultTool,256))
  3951.         {
  3952.             if(!AddPart(DefaultTool,WBenchMsg -> sm_ArgList[0] . wa_Name,256))
  3953.                 DefaultTool[0] = 0;
  3954.         }
  3955.  
  3956.         if(!DefaultTool[0])
  3957.             strcpy(DefaultTool,"MandelSquare");
  3958.  
  3959.         PictureIcon . do_DefaultTool    = DefaultTool;
  3960.  
  3961.         AnimIcon . do_DefaultTool    = DefaultTool;
  3962.  
  3963.             /* Called with Workbench arguments? */
  3964.  
  3965.         if(WBenchMsg -> sm_NumArgs > 1)
  3966.         {
  3967.                 /* Construct the full name. */
  3968.  
  3969.             if(NameFromLock(WBenchMsg -> sm_ArgList[1] . wa_Lock,DummyBuffer,256))
  3970.             {
  3971.                 if(!AddPart(DummyBuffer,WBenchMsg -> sm_ArgList[1] . wa_Name,256))
  3972.                     DummyBuffer[0] = 0;
  3973.                 else
  3974.                 {
  3975.                     struct DiskObject *Icon;
  3976.  
  3977.                         /* Read the icon and try to figure
  3978.                          * out whether the corresponding
  3979.                          * file is an animation or just
  3980.                          * a plain image.
  3981.                          */
  3982.  
  3983.                     if(Icon = GetDiskObject(DummyBuffer))
  3984.                     {
  3985.                         UBYTE *Value;
  3986.  
  3987.                         if(Value = FindToolType(Icon -> do_ToolTypes,"FILETYPE"))
  3988.                         {
  3989.                             if(MatchToolValue(Value,"ANIM"))
  3990.                                 IsAnim = TRUE;
  3991.                         }
  3992.  
  3993.                         FreeDiskObject(Icon);
  3994.                     }
  3995.                 }
  3996.             }
  3997.             else
  3998.                 DummyBuffer[0] = 0;
  3999.         }
  4000.     }
  4001.  
  4002.         /* No chance, use the default image. */
  4003.  
  4004.     if(!DummyBuffer[0])
  4005.         strcpy(DummyBuffer,"MandelSquare.Title");
  4006.  
  4007.         /* Try to read the selected image. */
  4008.  
  4009.     if(Info = LoadPicture(DummyBuffer))
  4010.     {
  4011.         LONG Error;
  4012.  
  4013.         if(Info -> MandelHeader . Iterations)
  4014.         {
  4015.             MinReal        = Info -> MandelHeader . MinReal;
  4016.             MinImaginary    = Info -> MandelHeader . MinImaginary;
  4017.             RealWidth    = Info -> MandelHeader . RealWidth;
  4018.             ImaginaryHeight    = Info -> MandelHeader . ImaginaryHeight;
  4019.  
  4020.             MaxIteration    = Info -> MandelHeader . Iterations - 1;
  4021.         }
  4022.  
  4023.         if(ModeNotAvailable(Info -> ViewModes) || (Info -> BitMapHeader . nPlanes > 5 && IntuitionBase -> LibNode . lib_Version < 39))
  4024.         {
  4025.             FreePicture(Info);
  4026.  
  4027.             Info = NULL;
  4028.         }
  4029.         else
  4030.         {
  4031.             if(Info -> BitMapHeader . w == Info -> BitMapHeader . h && !(Info -> BitMapHeader . h & 3))
  4032.             {
  4033.                 Square    = Info -> BitMapHeader . w;
  4034.                 Mode    = Info -> ViewModes;
  4035.                 Depth    = Info -> BitMapHeader . nPlanes;
  4036.  
  4037.                 SetProperties(Mode);
  4038.             }
  4039.             else
  4040.             {
  4041.                 FreePicture(Info);
  4042.  
  4043.                 Info = NULL;
  4044.             }
  4045.         }
  4046.  
  4047.         if(Error = GfxSetup())
  4048.         {
  4049.             if(Info)
  4050.                 FreePicture(Info);
  4051.  
  4052.             CloseAll(Error);
  4053.         }
  4054.         else
  4055.         {
  4056.             if(Info)
  4057.             {
  4058.                 BltBitMapRastPort(Info -> BitMap,0,0,RPort,0,0,Screen -> Width,Screen -> Height,0xC0);
  4059.  
  4060.                 LoadPalette(Screen,Info -> Palette,0);
  4061.  
  4062.                 GetPalette(Screen,Palette);
  4063.  
  4064.                 GotImage = TRUE;
  4065.             }
  4066.         }
  4067.  
  4068.         IterationSetup();
  4069.  
  4070.         if(Info)
  4071.             FreePicture(Info);
  4072.     }
  4073.     else
  4074.     {
  4075.         LONG    Error,
  4076.             Size;
  4077.  
  4078.         if(Size = GetModeSize(Mode))
  4079.         {
  4080.             struct DimensionInfo DimensionInfo;
  4081.  
  4082.             if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
  4083.             {
  4084.                 if(DimensionInfo . MaxDepth > 8)
  4085.                     Depth = 8;
  4086.                 else
  4087.                     Depth = DimensionInfo . MaxDepth;
  4088.             }
  4089.  
  4090.             Square = Size;
  4091.  
  4092.             SetProperties(Mode);
  4093.         }
  4094.         else
  4095.             CloseAll(RETURN_FAIL + 17);
  4096.  
  4097.         if(Error = GfxSetup())
  4098.             CloseAll(Error);
  4099.     }
  4100.  
  4101.         /* Are we supposed to load and replay an animation file? */
  4102.  
  4103.     if(IsAnim)
  4104.     {
  4105.         struct MinList *List;
  4106.  
  4107.         SetWait(Window);
  4108.  
  4109.         Window -> Flags |= WFLG_RMBTRAP;
  4110.  
  4111.         if(List = LoadAnim(DummyBuffer))
  4112.         {
  4113.             LONG Error = ValidateAnim(List,Screen);
  4114.  
  4115.             if(!Error)
  4116.             {
  4117.                 strcpy(AnimPlayName,DummyBuffer);
  4118.  
  4119.                 SetClear(Window);
  4120.  
  4121.                 ScreenToFront(Screen);
  4122.  
  4123.                 ActivateWindow(Window);
  4124.  
  4125.                 PlayAnim(List,Screen,CheckAbort);
  4126.  
  4127.                 SetWait(Window);
  4128.             }
  4129.  
  4130.             DeleteAnim(List);
  4131.         }
  4132.  
  4133.         Window -> Flags &= ~WFLG_RMBTRAP;
  4134.  
  4135.         ClrWait(Window);
  4136.  
  4137.         LoadPalette(Screen,Palette,0);
  4138.     }
  4139.     else
  4140.     {
  4141.         if(!GotImage)
  4142.         {
  4143.                 /* Set up working data. */
  4144.  
  4145.             MainMinReal        = MinReal;
  4146.             MainMinImaginary    = MinImaginary;
  4147.             MainRealWidth        = RealWidth;
  4148.             MainImaginaryHeight    = ImaginaryHeight;
  4149.  
  4150.                 /* Present the screen. */
  4151.  
  4152.             LoadPalette(Screen,Palette,0);
  4153.  
  4154.             ScreenToFront(Screen);
  4155.  
  4156.             ActivateWindow(Window);
  4157.  
  4158.             Running        = TRUE;
  4159.             NewCoords    = FALSE;
  4160.  
  4161.                 /* Generate the image. */
  4162.  
  4163.             RunMandelbrot(MinReal,MinReal + RealWidth,MinImaginary,MinImaginary + ImaginaryHeight,Window -> Width,Window -> Height);
  4164.         }
  4165.         else
  4166.         {
  4167.             strcpy(LastName,DummyBuffer);
  4168.  
  4169.                 /* Present the screen. */
  4170.  
  4171.             ScreenToFront(Screen);
  4172.  
  4173.             BlockWindow();
  4174.  
  4175.             ActivateWindow(Window);
  4176.  
  4177.             ReleaseWindow();
  4178.         }
  4179.  
  4180.         RealStep    = (RealWidth) / (double)Window -> Width;
  4181.         ImaginaryStep    = (ImaginaryHeight) / (double)Window -> Height;
  4182.     }
  4183.  
  4184.         /* The main input loop. */
  4185.  
  4186.     FOREVER
  4187.     {
  4188.         WaitPort(Window -> UserPort);
  4189.  
  4190.         HandleEvent();
  4191.  
  4192.             /* New display mode? */
  4193.  
  4194.         if(NewMode)
  4195.         {
  4196.             LONG    Error,
  4197.                 Size;
  4198.  
  4199.                 /* We have a bitmap to copy to the
  4200.                  * screen.
  4201.                  */
  4202.  
  4203.             if(GlobalBitMap)
  4204.             {
  4205.                 GfxCleanup();
  4206.  
  4207.                 Mode    = GlobalMode;
  4208.                 Depth    = GlobalDepth;
  4209.                 Square    = GlobalSize;
  4210.  
  4211.                 SetProperties(Mode);
  4212.  
  4213.                 NewMode    = FALSE;
  4214.  
  4215.                 if(Error = GfxSetup())
  4216.                     CloseAll(Error);
  4217.                 else
  4218.                 {
  4219.                     BltBitMapRastPort(GlobalBitMap,0,0,RPort,0,0,Screen -> Width,Screen -> Height,0xC0);
  4220.  
  4221.                     FreeCustomBitMap(GlobalBitMap,TRUE);
  4222.  
  4223.                     GlobalBitMap = NULL;
  4224.  
  4225.                     ScreenToFront(Screen);
  4226.  
  4227.                     BlockWindow();
  4228.  
  4229.                     ActivateWindow(Window);
  4230.  
  4231.                     LoadPalette(Screen,GlobalPalette,0);
  4232.                     GetPalette(Screen,Palette);
  4233.  
  4234.                     FreePalette(GlobalPalette);
  4235.  
  4236.                     GlobalPalette    = NULL;
  4237.  
  4238.                     NewCoords    = FALSE;
  4239.                     Running        = FALSE;
  4240.                     AreaActive    = FALSE;
  4241.  
  4242.                     IterationSetup();
  4243.  
  4244.                     ReleaseWindow();
  4245.                 }
  4246.             }
  4247.             else
  4248.             {
  4249.                 if(Size = GetModeSize(Mode))
  4250.                 {
  4251.                     Square = Size;
  4252.  
  4253.                     SetProperties(Mode);
  4254.                 }
  4255.                 else
  4256.                     CloseAll(RETURN_FAIL + 17);
  4257.  
  4258.                 NewMode    = FALSE;
  4259.  
  4260.                 SetProperties(Mode);
  4261.  
  4262.                 GfxCleanup();
  4263.  
  4264.                 if(Error = GfxSetup())
  4265.                     CloseAll(Error);
  4266.                 else
  4267.                 {
  4268.                     LoadPalette(Screen,Palette,0);
  4269.  
  4270.                     ScreenToFront(Screen);
  4271.  
  4272.                     ActivateWindow(Window);
  4273.  
  4274.                     MinReal        = MainMinReal;
  4275.                     MinImaginary    = MainMinImaginary;
  4276.                     RealWidth    = MainRealWidth;
  4277.                     ImaginaryHeight    = MainImaginaryHeight;
  4278.  
  4279.                     RealStep    = (RealWidth) / (double)Window -> Width;
  4280.                     ImaginaryStep    = (ImaginaryHeight) / (double)Window -> Height;
  4281.  
  4282.                     NewCoords    = TRUE;
  4283.                     AreaActive    = FALSE;
  4284.  
  4285.                     IterationSetup();
  4286.                 }
  4287.             }
  4288.         }
  4289.  
  4290.             /* Run the animation routine? */
  4291.  
  4292.         while(AnimRunning)
  4293.         {
  4294.             RunAnim();
  4295.  
  4296.             if(!AnimRunning)
  4297.             {
  4298.                 Running        = FALSE;
  4299.                 NewCoords    = FALSE;
  4300.             }
  4301.         }
  4302.  
  4303.             /* Restart with new coordinates. */
  4304.  
  4305.         if(NewCoords)
  4306.         {
  4307.             Running        = TRUE;
  4308.             NewCoords    = FALSE;
  4309.         }
  4310.  
  4311.             /* Run the image generation routines. */
  4312.  
  4313.         if(Running)
  4314.         {
  4315.             if(AreaActive)
  4316.                 RunAreaMandelbrot(RealStep,ImaginaryStep);
  4317.             else
  4318.             {
  4319.                 SetRast(RPort,0);
  4320.  
  4321.                 RunMandelbrot(MinReal,MinReal + RealWidth,MinImaginary,MinImaginary + ImaginaryHeight,Window -> Width,Window -> Height);
  4322.             }
  4323.         }
  4324.     }
  4325. }
  4326.